簡體   English   中英

獲取useState([{}])的前State(對象數組)

[英]Getting previous State of useState([{}]) (array of objects)

我正在努力獲得我輸入的真正以前的 state。 我認為我在寫這篇文章時發現的真正問題是我使用const inputsCopy = [...inputs]總是認為這會創建一個深層副本並且我不會改變原始數組。

const [inputs, setInputs] = useState(store.devices)

store.devices 看起來像這樣

devices = [{
 name: string,
network: string,
checked: boolean,
...etc
}]

我試圖在輸入更改后使用自定義掛鈎來獲取先前的值。 我正在嘗試檢查檢查的值是否已從真/假切換,因此我無法在 useEffect 掛鈎中運行我的自動保存功能。

function usePrevious<T>(value: T): T | undefined {
    // The ref object is a generic container whose current property is mutable ...
    // ... and can hold any value, similar to an instance property on a class
    const ref = useRef<T>();

    // Store current value in ref
    useEffect(() => {
        ref.current = value;
    }); // Only re-run if value changes

    // Return previous value (happens before update in useEffect above)
    return ref.current;
}

我還嘗試了另一個自定義掛鈎,它與 useState 類似,但具有 prev state 的第三個返回值。 看起來像這樣。

const usePrevStateHook = (initial) => {
    const [target, setTarget] = useState(initial)
    const [prev, setPrev] = useState(initial)

    const setPrevValue = (value) => {
        if (target !== value){ // I converted them to JSON.stringify() for comparison
            setPrev(target)
            setTarget(value)
        }
    }
    return [prev, target, setPrevValue]

}

在我從 api 獲取數據后,這些鈎子顯示了正確的 prevState,但是任何輸入更改都將 prev state 設置為相同的 prop 值。 我認為我的問題出在 mobx store.devices 的某個地方,我將初始 state 設置為,或者我在無法以某種方式復制/變異 state 時遇到問題。 我還嘗試檢查 setState 中的 prevState 是什么

setInputs(prev => {
    console.log(prev)
    return inputsCopy
})

寫完后,我認為我的問題可能是當輸入值發生變化並且 onChange 轉到我的 handleInputChange function 我創建了 state 輸入的副本,例如

const inputsCopy = [...inputs]
inputsCopy[i][prop] = value
setInputs(inputsCopy)

出於某種原因,我認為這會一直創建一個深層副本。 過去我在使用 redux 和其他一些事情時遇到過問題,我認為我沒有改變原始變量。

為所有回復干杯!

編輯:澄清我為什么要變異(不是我想要的)我在多個組件中有很多用於配置設備設置的輸入。 問題是我如何設置我的 onChange 函數<input type="text" value={input.propName} name="propName" onChange={(e) => onInputChange(e, index)} />

const onInputChange = (e, index) => {
    const value = e.target.value;
    const name = e.target.name;
    const inputsCopy = [...inputs]; // problem starts here
    inputsCopy[index][name] = value; // Mutated obj!?
    setInputs(inputsCopy);
}

這就是我認為我的自定義 prevState 鈎子不起作用的原因。 因為我正在變異它。

我的 AUTOSAVE 功能,我想要 DIFF 來比較 prevState 和 current

const renderCount = useRef(0)
useEffect(() => {
    renderCount.current += 1
    if (renderCount.current > 1) {
        let checked = false
       // loop through prevState and currentState for checked value
       // if prevState[i].checked !== currentState[i].checked checked = true

        if (!checked) {
            const autoSave = setTimeout(() => {
                // SAVE INPUT DATA TO API
            }, 3000)

            return () => {
               clearTimeout(autoSave)
            }
        }
    }
}, [inputs])

抱歉,我必須從 memory 中全部輸入。 不在辦公室。

如果我理解您的問題,您正在嘗試從之前的 state 值更新 state 並避免突變。 const inputsCopy = [...inputs]只是數組的淺拷貝,所以元素仍然引用前一個數組。

const inputsCopy = [...inputs] // <-- shallow copy
inputsCopy[i][prop] = value    // <-- this is a mutation of the current state!!
setInputs(inputsCopy)

Use a functional state update to access the previous state, and ensure all state, and nested state, is shallow copied in order to avoid the mutations. 使用Array.prototype.map制作inputs數組的淺表副本,使用迭代索引匹配您要更新的特定元素,然后還使用擴展語法制作元素 object 的淺表副本,然后覆蓋[prop]屬性值。

setInputs(inputs => inputs.map(
  (el, index) => index === i
    ? {
      ...el,
      [prop] = value,
    }
    : el
);

雖然這是一個 Redux 文檔,但不可變更新模式文檔是一個很好的解釋和示例。

摘抄:

更新嵌套對象

更新嵌套數據的關鍵是必須適當地復制和更新一層嵌套 對於那些學習 Redux 的人來說,這通常是一個困難的概念,並且在嘗試更新嵌套對象時經常會出現一些特定的問題。 這些會導致意外的直接突變,應該避免。

暫無
暫無

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

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