Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/rest/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React-本地存储&;状态-按钮切换渲染问题_Javascript_Ajax_Reactjs_Local Storage_Use Effect - Fatal编程技术网

Javascript React-本地存储&;状态-按钮切换渲染问题

Javascript React-本地存储&;状态-按钮切换渲染问题,javascript,ajax,reactjs,local-storage,use-effect,Javascript,Ajax,Reactjs,Local Storage,Use Effect,我一直在努力解决这个问题有一段时间了 我在使用当前状态显示切换按钮时遇到困难,该按钮可将项目添加到本地存储并将其删除。下面的代码可以正确添加和删除,但不能正确渲染 状态是镜像存储中的内容,但是(我相信)状态的异步性质允许按钮的呈现仅以一种方式工作。添加项目时,按钮将从添加(+)更改为删除(x),但不是相反。“上一个状态”将使按钮永久呈现为十字 这是对React功能的根本误解吗?此解决方案是否与其体系结构相抵触,或者是否存在允许实现此功能的小更改 很抱歉没有隔离代码的问题区域,但这是一个关键问题-

我一直在努力解决这个问题有一段时间了

我在使用当前状态显示切换按钮时遇到困难,该按钮可将项目添加到本地存储并将其删除。下面的代码可以正确添加和删除,但不能正确渲染

状态是镜像存储中的内容,但是(我相信)状态的异步性质允许按钮的呈现仅以一种方式工作。添加项目时,按钮将从添加(+)更改为删除(x),但不是相反。“上一个状态”将使按钮永久呈现为十字

这是对React功能的根本误解吗?此解决方案是否与其体系结构相抵触,或者是否存在允许实现此功能的小更改

很抱歉没有隔离代码的问题区域,但这是一个关键问题-我不知道是什么阻碍了我的努力

编辑:令人惊讶的是,CodeSandBox示例的功能与我所希望的一样,但是在本地托管这个问题仍然存在。是什么导致了这种性能差异

import React, { useState, useEffect } from "react";

function App() {
  const [data, setData] = useState(null);
  const [input, setInput] = useState("");
  const [item, setItem] = useState("");
  const [favourites, setFavourites] = useState([]);

  const favsLS = localStorage.getItem("drinks");

// Loads localStorage into state
  useEffect(() => {
    if (favsLS && favsLS.length > 15) {
      setFavourites(JSON.parse(localStorage.getItem("drinks")).filter(n => n));
    }
  }, []);

// Adds/Removes item from state
  useEffect(() => {
    if (!JSON.stringify(favourites).includes(item.id)) {
      setFavourites(favourites => [...favourites, item]);
    } else {
      favourites.forEach((drink, index) => {
        let favs = favourites;
        if (item.id === drink.id) {
          favs.splice(index, 1);
          setFavourites(favs);
        }
      });
    }
  }, [item]);

// Commits state to localStorage
  useEffect(() => {
    localStorage.setItem("drinks", JSON.stringify(favourites));
  }, [favourites]);

  const handleChange = e => {
    setInput(e.target.value);
  };

// AJAX call
  const handleSubmit = async e => {
    e.preventDefault();
    let cocktail = input;
    const res = await fetch(
      `https://www.thecocktaildb.com/api/json/v1/1/search.php?s=${cocktail}`
    );
    const data = await res.json();
    setData(data.drinks);
    setInput("");
  };

  return (
    <div className='field'>
      <h3>Search</h3>
      <form onSubmit={handleSubmit}>
        <input placeholder={"Enter..."} value={input} onChange={handleChange} />
        <input type='submit' value='Submit' />
      </form>
      <div className='cocktails'>
        {data ? data.map((item, i) => (
              <div key={item.idDrink} className='card'>
                <h3>{item.strDrink}</h3>
                <div>
                  <button
                    className='fav-btn'
                    onClick={() => {
                      setItem({
                        id: item.idDrink,
                        name: item.strDrink,
                        image: item.strDrinkThumb
                      });
                      setFavourites(
                        JSON.parse(localStorage.getItem("drinks")).filter(n => n));
                    }}>
                    {JSON.stringify(favourites).includes(item.idDrink) ? "x" : "+"}
                  </button>
                  <img
                    className='cocktailImg'
                    src={item.strDrinkThumb}
                    alt=''
                  />
                </div>
              </div>
            ))
          : ""}
      </div>
    </div>
  );
}

export default App;

import React,{useState,useffect}来自“React”;
函数App(){
const[data,setData]=useState(null);
const[input,setInput]=useState(“”);
const[item,setItem]=useState(“”);
const[favorites,setfavorites]=useState([]);
const favsLS=localStorage.getItem(“饮料”);
//将本地存储加载到状态
useffect(()=>{
如果(favsLS&&favsLS.length>15){
setFavorites(JSON.parse(localStorage.getItem(“饮料”)).filter(n=>n));
}
}, []);
//从状态添加/删除项
useffect(()=>{
if(!JSON.stringify(收藏夹).includes(item.id)){
设置收藏夹(收藏夹=>[…收藏夹,项目];
}否则{
最喜欢的。forEach((饮料,索引)=>{
让favs=最喜欢的;
如果(item.id==drink.id){
favs.拼接(索引1);
最喜欢的人(FAV);
}
});
}
},[项目];
//将状态提交到本地存储
useffect(()=>{
setItem(“饮料”,JSON.stringify(收藏夹));
},[热门];
常量handleChange=e=>{
设置输入(如目标值);
};
//AJAX调用
const handleSubmit=async e=>{
e、 预防默认值();
让鸡尾酒=输入;
const res=等待取数(
`https://www.thecocktaildb.com/api/json/v1/1/search.php?s=${鸡尾酒会}`
);
const data=wait res.json();
setData(数据.饮料);
设置输入(“”);
};
返回(
搜寻
{data?data.map((项目,i)=>(
{item.strDrink}
{
设定项({
id:item.idDrink,
名称:item.strDrink,
图像:item.strDrinkThumb
});
最爱(
parse(localStorage.getItem(“饮料”)).filter(n=>n));
}}>
{JSON.stringify(收藏夹).includes(item.idDrink)?“x”:“+”}
))
: ""}
);
}
导出默认应用程序;

Panther发现了问题-两次调用更新相同的状态值。通过在渲染中删除对SetFavorites的调用,并将筛选器(.filter(n=>n))移动到其相应的useEffect,该错误被删除。

“CodeSandBox to example”请使用演示问题的示例更新您的问题,最好是使用堆栈片段(工具栏按钮
[]
)运行问题。堆栈代码段支持React,包括JSX。“令人惊讶的是,CodeSandBox示例的功能与我所希望的一样…”然后您必须找出该环境与您的环境之间的区别。做一个堆栈代码片段可能会帮助您做到这一点,但是…缺少一些东西。单击按钮调用
setItem
哪个inturn会触发
useffect
哪个inturn会更新收藏夹。但您也在onClick方法中调用setfavorites。优化这些更新将得到正确的结果,希望。太棒了!谢谢你们两位的回复。黑豹,这确实是个问题!您为我节省了很多时间,谢谢:)和TJ,我将在将来正确格式化。