React - 正确触发代表来自 React 组件的状态更改事件的回调

问题描述 投票:0回答:3

在一个应用程序中,我正在构建一个自定义范围滑块。我有一个保持当前值的状态,还有一个暴露在此内部状态更改时触发的回调的道具。以下是我目前的做法:

const Slider = ({onChange}) => {
  const [value, setValue] = useState(0)
  // ...
  useEffect(() => onChange?.(value), [value, onChange])
  // ...
}

这里的问题是

onChange
是在组件加载时触发的,因为
onChange
是依赖列表的一部分。但是如果我从列表中删除它,它不会触发更改回调的定义。

这里正确的做法是什么?

  1. 以上是正确的,
    onChange
    的订阅者应该考虑到即使实际上没有发生变化也会调用它。
  2. onChange
    在设置值状态的同一个函数中触发 - 但它可能发生在多个地方,我需要确保它在所有需要的地方被调用。
javascript reactjs react-hooks callback state
3个回答
0
投票

更新的答案,这是一个从头开始功能齐全的滑块。

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

0
投票

关键有两点: 第一个,OnChange()在这里有两种不同的含义:一种是反馈值的变化,一种是反馈onChange()本身的变化。两者可能应该分开。 第二点,useEffect()的设计目的是针对一个已经给定的参数执行行为,它的重点是“获取一个新的值并做一些事情”,比如根据一个新的url数据进行查询。 useEffect() 实际上是一种基于某些特定关注点试图解耦代码的设计。如果不使用useEffect()处理业务逻辑,就要考虑“首次运行”的重复代码问题。但是 OnChange() 专注于不同的事情。 OnChange() 本质上高度绑定到 setState()。正如您所说,OnChange() 应该只关心数据变化,这与 useEffect() 不同。因此,更好的设计可能是不使用useEffect(),而是将setState()包装起来,并在这个包装好的函数中调用OnChange()。如果每次获得您关心的值时您都有事情要做,请使用 useEffect()。 useEffect()自带的“准备结束关注的最后一个值的副作用”函数钩子,可以处理每次值变化时要做的事情。


0
投票

为了让您的实施工作如您所愿,您需要做两件事:

  1. 防止在第一次渲染时不必要地调用
    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])
  // ...
}
  1. 确保传递给
    onChange
    组件的
    Slider
    回调是使用 React 的
    useCallback
    钩子记忆的,它可以防止在
    useEffect
    组件内不必要地调用
    Slider
    组件,其中
    onChange
    由于重新渲染而在依赖列表中回调外部组件。
© www.soinside.com 2019 - 2024. All rights reserved.