【发布时间】:2023-01-12 08:51:54
【问题描述】:
通常我会有一个由两个输入组成的输入。例如,带有数字输入的滑块,或带有十六进制输入的颜色选择器。这些组件需要在用户完成对它们的操作时宣布状态更改,但它们需要相互通知每一个改变。每个都需要以比父级更细的粒度来跟踪另一个的变化。
例如,如果用户拖动滑块,则数字输入应始终代表滑块的值。当用户输入数字时,滑块应该跳来跳去并保持同步。当用户释放滑块时,应从组件触发 onChange 回调,以便父级可以更新状态。
为清楚起见:在下面的示例中,如果用户在左侧输入上单击“向上”10 次,我希望看到每个更改都反映在左侧输入上,但当组件失去焦点时,父项中只有 1 个更改。
下面是一些实现此行为的代码。这段代码确实确切地我想让它做什么。对于我的用例,该行为 100% 正确。但是,我不想在这个组件中有一个useEffect。那是我的问题“我怎样才能删除这个 useEffect?”
import "./styles.css";
import { useEffect, useState } from "react";
export default function App() {
const [state, setState] = useState(0);
// this is called whenever the user is "done" manipulating the compound input
const handleChange = (change) => {
console.log("change", change);
setState(change);
};
return (
<div className="App">
<CompoundInput value={state} onChange={handleChange} />
</div>
);
}
function CompoundInput(props) {
const [internalState, setInternalState] = useState(props.value);
// this is a _controlled_ component, so this internal state
// must also track the parent state
useEffect(() => {
setInternalState(props.value);
}, [props.value]);
// each input updates to reflect the state of the other input
// but does so without the parent knowing
return (
<>
<input
type="number"
value={internalState}
onChange={(e) => setInternalState(e.target.value)}
onBlur={(e) => props.onChange(e.target.value)}
/>
<input
type="number"
value={internalState}
onChange={(e) => setInternalState(e.target.value)}
onBlur={(e) => props.onChange(e.target.value)}
/>
</>
);
}
https://codesandbox.io/s/compassionate-sun-8zc7k9?file=/src/App.js
由于 useState,我发现这个实现令人沮丧。我的感觉是,当遵循这种模式时,最终每个组件都需要一点 useEffect 来跟踪受控组件的内部状态。我的感觉是应该用useEffect来实现效果这并不是真正的效果。
有没有办法实现这个组件没有使用效果?
【问题讨论】:
-
将 setState 向下传递给子组件,并在 onChange 触发时调用它们。然后状态将触发重新呈现您的组件,因此您不必使用 useEffect。 ,这对你的情况满意吗?
-
不,也许我的问题不清楚:/父母应该只要在调用
onBlur时更新。onChange回调用于在用户更新它们时保持左右输入同步。如果用户在左侧输入中键入 123,然后在外部单击,则右侧输入将取值 1,然后是 12,然后是 123...但是onChange回调将仅通过123调用一次。那有意义吗? -
我认为根本不需要效果挂钩。如果你改变父
state,孩子应该重新渲染,因为它的道具改变了~codesandbox.io/s/dreamy-ellis-1086v1?file=/src/App.js -
@Ziggy 不正是我添加的链接中发生的事情吗?请注意,当您使用箭头按钮时,数字输入不会触发模糊事件
-
直接回答你的问题......是的。把效果钩去掉就好了,多余。我不确定这是否值得一个完整的答案
标签: javascript reactjs react-hooks