繁体   English   中英

从prop事件处理程序设置时,反应状态会重置

React state resets when set from prop event handler

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我一生无法弄清楚发生了什么,但是由于某些原因,当单击“单击我”时,数字会按预期增加。 当子组件触发点击时,它将重置状态,并始终打印0。

function Child(props: {
    onClick?: (id: string) => void,
}) {
    const ref = useCallback((ref) => {
        ref.innerHTML = 'This Doesnt';
        ref.addEventListener('click',() => {
            props.onClick!('')
        })
    }, [])
    return (<div ref={ref}></div>)
}

function Parent() {
  const [number, setNumber] = useState(0);
  return <div>
            <div onClick={() => {
                setNumber(number + 1);
                console.log(number);
            }}>
                This Works
            </div>
            <Child
                onClick={(id) => {
                    setNumber(number + 1);
                    console.log(number);;
                }}
            />
        </div>
}

这是问题的演示: https : //jscomplete.com/playground/s333177

2 个回复

正确地在每个渲染上都重新创建了父组件中的两个onClick处理程序,因为它们在number状态字段上具有关闭符。

问题是,发送给Child组件的onClick属性在ref回调中使用,由于依赖项列表为空,因此仅在初始渲染期间做出反应。 因此,Child在后续渲染中收到的onClick道具根本无法使用。

尝试通过删除依赖项参数或发送props.onClick来解决此错误,如依赖项列表中所述,由于文档中提到的警告,我们陷入了困境。 https://reactjs.org/docs/refs-and-the-dom.html

因此,您添加了空处理,并且现在看到已更新的回调被调用,但是...由于我们尚未删除这些事件侦听器,因此也会调用所有较早的回调。

const ref = useCallback((ref) => {
    if(!ref) return;
    ref.innerHTML = 'This Doesnt';
    ref.addEventListener('click',() => {
        props.onClick!('')
    })
}, [props.onClick])

我相信这只是作为学习挂钩的一部分而进行的实验,否则,无需采取in回的方式从ref回调中调用onClick 只是将它作为div道具传递。

编辑:
根据您的评论,由于这不仅是实验,还简化了一些真正的要求,其中需要通过addEventListener设置点击处理程序,这是一种可能的解决方案:

const ref = useRef(null);
useEffect(() => {
    if(!ref.current) return;
    ref.current.innerHTML = 'This Doesnt';
    const onClick = () => props.onClick!('');
    ref.current.addEventListener('click',onClick)

    // return the cleanup function to remove the click handler, which will be called before this effect is run next time.
    return () => {ref.current.removeEventListener("click", onClick)}
}, [ref.current, props.onClick]);

基本上,我们需要使用useEffect以便有机会在添加新监听器之前删除旧的监听器。

希望这可以帮助。

function Child(props: {
    onClick?: (id: string) => void,
}) {
    function handleClick() {
      props.onClick('')
    }
    const ref = useRef();
    useEffect(() => {
      ref.current.innerHTML = 'This Doesnt';
      ref.current.addEventListener('click', handleClick)
      return () => { ref.current.removeEventListener('click', handleClick); }
    }, [props.onClick])

    return (<div ref={ref}></div>)
}

@ckder几乎可以使用,但是console.log显示了从0到当前数字值的所有数字。 事件侦听器的问题是在卸载子组件之后尚未删除的事件侦听器,因此要达到此目的,我在卸载侦听器的地方使用了useEffect和return函数。

1 通过事件处理程序更改反应状态

我的问题是: 如何使用多选更改默认设置对象的状态? 假设我有状态checkDevice和checkCountry ,所以在下面的小提琴中,我确实将所有值都设置为false 。 我只想将在多选下拉列表中选择的那些属性的值设置为true 。 例如 :在多选中,如果我只是选择U ...

2 在状态属性内的事件处理程序中设置状态

我在从该状态内的事件更新状态时遇到问题。 我的意思是我有一个动态表单,并且这个表单的属性中必须有一个事件。 我用我的问题编写了一个小组件,代码在 url https://codesandbox.io/s/material-demo-4wsib ...

3 使用.prop()设置单选按钮不会触发事件处理程序

我有一个JavaScript函数,用于侦听Radio button上的更改,以便执行下一批代码。 但是,我发现当我实际点击按钮时,它与在代码中设置它不同(通过.prop("checked",true); )。 为什么当我更改通过.prop()选择哪个单选按钮时,它不会触发事件处理程序.cha ...

2014-08-15 03:58:53 1 1217   jquery
4 重置输入文件时删除事件处理程序

我有以下代码重置输入文件: 但是,我注意到,如果使用特定的输入文件,则不会处理其事件触发。 因此,此代码用于在更改文件输入时处理事件: 似乎是什么问题? 您的回复将不胜感激... ...

5 重置触摸事件的事件处理程序

我的网站www.philipmadeley.com在导航中遇到“接触”事件时遇到问题。 似乎可以处理第一个“触摸”,但是其余的则不起作用。 我厌倦了几种解决方案,但是我不是那么技术专业,所以我想我可能已经忽略了某些事情……无论如何,我似乎都找不到答案。 希望能对您有所帮助。 ...

6 在 React 的事件处理程序中获取组件的 prop

有一个带有key prop 和onClick事件处理程序的 React 组件。 我需要创建一些这些组件,并将它们的key作为 click 事件处理程序的参数。 但是如果参数是value变量,则在 for 循环迭代后取其最终值。 例如,如果我创建三个部件, handleClick函数获取value = ...

8 为什么在从事件处理程序分配状态时需要设置组件的值?

我是新手反应,只是按照一些教程,我找不到答案 给定状态input并在我的组件中submit ,这两个输入给了我相同的结果来更改state.submit 如果handleChange函数已经使用给定的事件设置了状态,为什么我仍然需要设置value = {this.state.input} ? ...

2020-01-10 08:04:43 1 62   reactjs
9 用react-redux绑定事件处理程序prop

从容器到演示文稿小部件声明事件处理程序的正确方法是什么,以便我可以访问事件处理程序功能中的其他道具? 当前,每当单击事件发生时, this.props.handle_click事件处理程序都会记录undefined的日志。 如果我想访问this.props.foo ,正确的方法是什么? ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM