提问人:PSK 提问时间:4/8/2023 更新时间:4/9/2023 访问量:164
React - 正确触发表示 react 组件状态更改事件的回调
React - Properly triggering callback that represents a state change event from react component
问:
在一个应用程序中,我正在构建一个自定义范围滑块。我有一个维护当前值的状态,还有一个道具,它暴露了在更改此内部状态时触发的回调。以下是我目前的做法:
const Slider = ({onChange}) => {
const [value, setValue] = useState(0)
// ...
useEffect(() => onChange?.(value), [value, onChange])
// ...
}
这里的问题是,由于是依赖项列表的一部分,因此在组件加载时触发。但是,如果我将其从列表中删除,则不会在更改回调的定义时触发。onChange
onChange
正确的方法是什么?
- 以上是正确的,订阅者应该考虑到即使实际上没有发生更改,它也会被调用。
onChange
- 在设置值状态的同一函数中触发 - 但它可能发生在多个地方,我需要确保在所有需要的地方调用它。
onChange
答:
更新的答案,这是一个从头开始的滑块,功能齐全。
import {useState} from "react";
const CustomSlider = ({min, max, value, onChange}) => {
const [sliderValue, setSliderValue] = useState(value);
const handleSliderChange = (event) => {
const newValue = parseInt(event.target.value);
setSliderValue(newValue);
onChange(newValue);
}
return (
<div>
<input
type="range"
min={min}
max={max}
value={sliderValue}
onChange={handleSliderChange}
/>
</div>
)
}
export default function App() {
const [value, setValue] = useState(0)
return (
<div>
<CustomSlider
min={0}
max={100}
value={value}
onChange={val => setValue(val)}
/>
{value}
</div>
);
}
评论
有两个关键点: 第一个,OnChange()在这里有两个不同的含义:一个是反馈值的变化,另一个是反馈onChange()本身的变化。这两者可能应该分开。 第二点是 useEffect() 被设计为对已经给出的参数执行行为,它的重点是“获取一个新值并做一些事情”,例如基于新的 url 数据进行查询。useEffect() 实际上是一种尝试根据某些特定关注点解耦代码的设计。如果不使用 useEffect() 处理业务逻辑,则应考虑“首次运行”重复代码的问题。但是 OnChange() 关注的是不同的东西。OnChange() 本质上与 setState() 高度绑定。正如你所说,OnChange() 应该只关心数据变化,这与 useEffect() 不同。因此,更好的设计可能不是使用 useEffect(),而是包装 setState(),并在这个包装函数中调用 OnChange()。如果每次获得您关心的值时都有事情要做,请使用 useEffect()。useEffect() 自带的 “prepare to end the side effect of the last value involved” 函数钩子可以处理每次值更改时要做的事情。
为了使你的实现按你的预期工作,你需要做两件事:
- 防止在第一次渲染时不必要地调用回调,为此,您可以检查是否已挂载,并且仅在已挂载时调用,以下需要对内部组件进行更改:
onChange
Slider
onChange
Slider
useEffect
Slider
const Slider = ({ onChange }) => {
const [value, setValue] = useState(0)
// ...
const isMounted = useRef(false)
useEffect(() => {
if (isMounted.current === false) {
isMounted.current = true
return
}
onChange?.(value)
return () => {
isMounted.current = false
}
}, [value, onChange])
// ...
}
- 确保使用 React 的钩子记住传递给组件的回调,它可以防止由于外部组件的重新渲染而导致依赖列表中的 callback 对内部组件的不必要调用。
onChange
Slider
useCallback
useEffect
Slider
onChange
评论
useEffect
onChange
value
onChange
value
onChange
Slider