簡體   English   中英

在自定義掛鈎中創建數組是在每次 state 更改時重新呈現值

[英]Creating an array in the custom hook is re rendering value at every state change

我在 React Native 中創建自定義鈎子時遇到了 useEffect 和 useState 的問題,導致無限循環。

我創建了一個小點心來舉例說明正在發生的事情:

import React, { useEffect, useState, useMemo } from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';

export default function App() {
   const [testStateVariable, setTestStateVariable] = useState(false);

    const useCustomHookTest = () => {
        let testVar = ""; // Change the value "" to [] to see the problem;
        return useMemo(
            () => ({
                testVar,
            }),
            [testVar],
            );
    };
    
    var { testVar } = useCustomHookTest();
    
    useEffect(() => {
        console.log("CHANGE OF testVar!")
    }, [testVar]);

    return (
        <View style={styles.container}>
             <Button title="Change a state to true" onPress={() => {setTestStateVariable(true)}}/>
             <Button title="Change a state to false" onPress={() => {setTestStateVariable(false)}}/>
        </View>
    );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
});

基本上,當我在自定義掛鈎中使用數組時,它會在每次 state 發生變化時重新呈現並更改變量的值。 您可以看到將 testVar 的值更改為 [] 並按下兩個按鈕來更改狀態,每次 state 更改時都會觸發 useEffect,但是當值為“”時不會發生這種情況。

我嘗試使用 useMemo 但它沒有用,

有人有解決這個問題的方法嗎?

謝謝

基本要點是"" === ""始終為真,而[] === []始終為假。 字符串雖然類似於對象,但在某種程度上被視為原始類型,因為它們始終等於自身。 另一方面,Arrays 是特殊的 Javascript 對象,兩個聲明的對象永遠不會嚴格相等。

試試吧!

 console.log('"" === ""', "" === ""); // true console.log('[] === []', [] === []); // false

當你分配let testVar = ""; 每個渲染周期testVar始終等於上一個渲染的最后一個值,因此useMemo掛鈎返回先前計算的記憶值。

const useCustomHookTest = () => {
  let testVar = "";
  return useMemo(
    () => ({
      testVar
    }),
    [testVar] // "" === "" true, dependency didn't "change".
  );
};

現在對比一下當你賦值let testVar = ""; 每個渲染周期,依賴項現在總是一個新的數組引用,因此不嚴格相等,並且useMemo掛鈎重新計算其記憶值。

const useCustomHookTest = () => {
  let testVar = []; // <-- new array each render
  return useMemo(
    () => ({
      testVar
    }),
    [testVar] // [] === [] false, new memoized value
  );
};

由於記憶值是一個的 object, useEffect掛鈎的依賴項現在看到一個新的 object,即{ testVar: true } === { testVar: false }不是假的,因為testVar屬性改變了,而是因為{} === {}也是錯誤的,原因與[] === []相同。 這是一個新的 object 參考。

除此之外,您還不清楚您希望使用以下代碼模式完成什么:

export default function App() {
  const [testStateVariable, setTestStateVariable] = useState(false);

  const useCustomHookTest = () => {
    let testVar = "";
    return useMemo(
      () => ({
        testVar
      }),
      [testVar]
    );
  };

  var { testVar } = useCustomHookTest();

  useEffect(() => {
    console.log("CHANGE OF testVar!");
  }, [testVar]);

  return (
    <View style={styles.container}>
      <Text>{testStateVariable.toString()}</Text>
      <Button
        title="Change a state to true"
        onPress={() => {
          setTestStateVariable(true);
        }}
      />
      <Button
        title="Change a state to false"
        onPress={() => {
          setTestStateVariable(false);
        }}
      />
    </View>
  );
}

useCustomHookTest掛鈎在每個渲染周期都被重新聲明,因此在父組件的每個渲染周期都會重新創建內部的任何內容。

如果您的問題基本上是如何使用 arrays 作為 React 鈎子依賴項,那么不幸的是沒有任何好的解決方案。 兩個領先的解決方案要么實施深度相等性檢查,要么簡單地對數組進行 JSON 字符串化。

JSON.stringify 示例:

const useCustomHookTest = () => {
  let testVar = [];
  return { testVar };
};

export default function App() {
  const [testStateVariable, setTestStateVariable] = useState(false);

  const { testVar } = useCustomHookTest();

  useEffect(() => {
    console.log("CHANGE OF testVar!");
  }, [JSON.stringify(testVar)]); // <-- JSON stringify dependency

  return (
    <View style={styles.container}>
      <Text>{testStateVariable.toString()}</Text>
      <Button
        title={`Change a state to ${(!testStateVariable).toString()}`}
        onPress={() => {
          setTestStateVariable((t) => !t);
        }}
      />
    </View>
  );
}

編輯 creating-an-array-in-the-custom-hook-is-re-rendering-value-at-every-state-change

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM