javascript - 获取之前的 useState([{}]) 状态(对象数组)

标签 javascript reactjs react-hooks use-state

我正在努力获取输入的真实先前状态。 我认为我在写这篇文章时发现的真正问题是我对 const inputsCopy = [...inputs] 的使用一直认为这会创建一个深拷贝,我不会改变原始数组。

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

store.devices 看起来像这样

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

我试图使用自定义 Hook 在输入更改后获取先前的值。 我正在尝试检查检查的值是否已从 true/false 切换,因此我无法在 useEffect Hook 中运行我的自动保存功能。

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;
}

我还尝试了另一个自定义 Hook ,它的工作方式与 useState 类似,但具有前一个状态的第三个返回值。看起来像这样。

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]

}

这些 Hook 在我从 api 获取数据后显示正确的 prevState,但任何输入更改都将 prev 状态设置为相同的 prop 值。 我认为我的问题出在我将初始状态设置为的 mobx store.devices 的某个地方,或者我遇到了无法以某种方式复制/改变状态的问题。 我也试过检查 setState 中的 prevState 是什么

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

写完之后,我认为我的问题可能是当输入值发生变化并且 onChange 转到我的 handleInputChange 函数时,我创建了状态输入的副本,例如

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 Hook 无法正常工作的原因。因为我正在改变它。

我的 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])

抱歉,我不得不凭内存输入所有内容。不在办公室。

最佳答案

如果我理解你的问题,你正在尝试从以前的状态值更新状态并避免突变。 const inputsCopy = [...inputs] 只是数组的浅拷贝,因此元素仍然引用前一个数组。

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

使用功能状态更新来访问以前的状态,并确保所有状态和嵌套状态都被浅拷贝以避免突变。使用 Array.prototype.map 制作 inputs 数组的浅拷贝,使用迭代索引匹配要更新的特定元素,然后还使用 Spread生成那个元素对象的浅拷贝的语法,然后覆盖[prop]属性值。

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

尽管这是一个 Redux 文档,Immutable Update Patterns文档是一个很好的解释和示例。

摘录:

Updating Nested Objects

The key to updating nested data is that every level of nesting must be copied and updated appropriately. This is often a difficult concept for those learning Redux, and there are some specific problems that frequently occur when trying to update nested objects. These lead to accidental direct mutation, and should be avoided.

关于javascript - 获取之前的 useState([{}]) 状态(对象数组),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70310881/

相关文章:

reactjs - 使用 react-testing-library 测试 useContext()

reactjs - 如何从 useState Hook 访问 setState 中的回调

javascript - Google Drive API - 复制现有的电子表格文件并使用 JavaScript Client API 设置 "title"

javascript - 是否可以返回 0 的小数点后两位的浮点值?

reactjs - React contenteditable光标跳转到开头

javascript - 如何从自定义 react 钩子(Hook)丰富数据

javascript - jQuery 延迟的怪异

javascript - 如何使用 JavaScript .forEach 获取迭代 JSON 对象和 JSON 数组

javascript - 如何将 dispatch 传递到 prop 之类的组件中?

javascript - 如何使用导入的函数作为 promise 。 Object(...)(...).then 不是函数