获取之前的 useState([{}]) 状态(对象数组)
Getting previous State of useState([{}]) (array of objects)
我正在努力获取输入的真实先前状态。
我认为我在写这篇文章时发现的真正问题是我对 const inputsCopy = [...inputs]
的使用,一直认为这会创建一个深层副本,我不会改变原始数组。
const [inputs, setInputs] = useState(store.devices)
store.devices 看起来像这样
devices = [{
name: string,
network: string,
checked: boolean,
...etc
}]
我试图使用自定义挂钩在输入更改后获取先前的值。
我正在尝试检查检查的值是否已从 true/false 切换,因此我无法 运行 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 类似,但对前一个状态有第三个 return 值。看起来像这样。
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 状态设置为相同的属性值。
我认为我的问题出在我将初始状态设置为的 mobx store.devices 的某个地方,或者我遇到的问题不是 copying/mutating 状态。
我也试过检查 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 挂钩无法正常工作的原因。因为我正在变异它。
我的 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 Syntax 对 [=26 进行浅拷贝=]那个元素对象,然后覆盖[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.
我正在努力获取输入的真实先前状态。
我认为我在写这篇文章时发现的真正问题是我对 const inputsCopy = [...inputs]
的使用,一直认为这会创建一个深层副本,我不会改变原始数组。
const [inputs, setInputs] = useState(store.devices)
store.devices 看起来像这样
devices = [{
name: string,
network: string,
checked: boolean,
...etc
}]
我试图使用自定义挂钩在输入更改后获取先前的值。 我正在尝试检查检查的值是否已从 true/false 切换,因此我无法 运行 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 类似,但对前一个状态有第三个 return 值。看起来像这样。
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 状态设置为相同的属性值。 我认为我的问题出在我将初始状态设置为的 mobx store.devices 的某个地方,或者我遇到的问题不是 copying/mutating 状态。 我也试过检查 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 挂钩无法正常工作的原因。因为我正在变异它。
我的 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 Syntax 对 [=26 进行浅拷贝=]那个元素对象,然后覆盖[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.