在循环中调用异步函数的 useEffect

时间:2021-01-28 18:08:37

标签: javascript reactjs react-native

我的情况是这样的:

export default function Component({ navigation }) {
    const [ item, setItem ] = useState([]);
    
    useEffect(() => {
        AsyncStorage.getItem('someItem')
        .then(data => JSON.parse(data))
        .then(jsonData => {
            setItem(jsonData);
        })
        .catch(error => {});
    }, [item]);

问题是 useEffect 似乎在循环中被调用,即使“item”没有改变。如果我从依赖项数组中删除 item,它只会被调用一次,并且当 item 更改时,组件不会重新渲染。有解决办法吗?

这样解决:

export default function Component({ navigation }) {
        const [ item, setItem ] = useState([]);
        const [ update, setUpdate ] = useState(false);

        const handleUpdate = () => {
            setUpdate(!update);
        }
        
        useEffect(() => {
            AsyncStorage.getItem('someItem')
            .then(data => JSON.parse(data))
            .then(jsonData => {
                setItem(jsonData);
            })
            .catch(error => {});
        }, [update]);

然后在我想更新项目的状态时调用 handleUpdate(或将其传递给子组件并让子组件调用它)。

2 个答案:

答案 0 :(得分:4)

你有一个无限循环: 您发送给 BigInteger 的第二个参数是依赖项数组。每次这些依赖项中的一个发生变化时 - 将调用 radix 的第一个参数,即回调。所以你这样做:

每次 useEffect() 更改 - 运行更改 useEffect() 的代码(因为回调将值设置为 item

注意:useEffect 也会首先调用一次发送给它的回调。

答案 1 :(得分:1)

问题与 this post 中描述的相同。当您使用对象作为依赖项时,useEffect 认为它在每次渲染时都不同。由于您使用的是一个数组,它是一个对象,因此您会得到无限循环。假设您的状态变量是一个原始类型,如字符串或数字,那么它不会继续呈现,因为 useEffect 将能够确定该值没有改变。

因此,在您的特定情况下可能的解决方案,因为有一个 JSON 字符串被返回,可以使用该 JSON 字符串作为并行状态变量来检查更改。

考虑这样的事情:

const simulateCall = () => Promise.resolve('["ds","1234sd","dsad","das"]')

export default function App() {
  const [state, setArrayState] = React.useState([])
  const [stringState, setStringState] = React.useState('')

  React.useEffect(() => {
    simulateCall()
    .then(data => {
      setStringState(data);
      setArrayState(JSON.parse(data));
    })
    .catch(error => console.log(error));
}, [stringState]);


  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      {state.map((item, i) => <div key={i}>{item}</div>)}

    </div>
  );
}