Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React hooks组件中,定义的方法取不到新的state值的坑 #4

Open
wqhui opened this issue Jul 7, 2020 · 0 comments
Open

Comments

@wqhui
Copy link
Owner

wqhui commented Jul 7, 2020

项目中使用postal订阅方法时,使用react hooks useEffect去监听方法时,发现取到的state一直是旧的值,然后重写了例子。

假设有个需求,父组件修改颜色,父组件会把该颜色传到子组件,子组件每次点击会打印当前自己state里面的颜色。

这里子组件有两个监听事件,一个是原生dom的监听方式,一个是react提供的监听,再测试的时候发现二者表现不同,所以写了两个。

其他前端有趣的例子和坑合集:https://github.com/wqhui/blog
直接预览:https://codepen.io/Lik_Lit/pen/jOPJbbG

//子组件代码
function Content ({theme}){
  const [themeState,setTheme] = React.useState(theme)
  const [reactThemeState,setReactThemeState] = React.useState({})
  const [nativeThemeState,setNativeThemeState] = React.useState({})
  const ref = React.useRef(null)
      
    const fun = (e)=>{
      e.target.innerText=== 'react点击' ? setReactThemeState(themeState):setNativeThemeState(themeState)
    }
    
    //1.按照以前的写法,在didMount监听一次就可以
    React.useEffect(()=>{ //监听click
      ref.current.addEventListener('click',fun)
      return ()=>{
        ref.current.removeEventListener('click',fun)
      }
    },[])
    
     React.useEffect(()=>{//props 改变 设置state
      setTheme(theme)
    },[theme])
    
    return (
      <div>
        <p>当前颜色:{themeState.foreground}</p>
        <div className='button-area'>
          <div onClick={fun}>react点击</div>
          <div ref={ref} >原生点击</div>
        </div>
        <p>react监听点击时颜色:{reactThemeState.foreground}</p> 
        <p>原生监听点击时颜色:{nativeThemeState.foreground}</p>
      </div>
    );
   
}

一开始点击显示颜色都是正常的,但是当我点击父组件切换了颜色的时候,发现二者输出的颜色不同,
在这里插入图片描述
这是由于hooks useEffect监听时监听方法里的依赖参数,应当写到useEffect第二个参数里,我这个原生监听依赖于state里面的themeState,所以得对监听的useEffect做个修改

    React.useEffect(()=>{ //监听click
      ref.current.addEventListener('click',fun)
      return ()=>{
        ref.current.removeEventListener('click',fun)
      }
    },[themeState])//themeState改变则重新监听 这里改成props的theme也是错误的

这个时候监听方法取到到state就是新的值
在这里插入图片描述

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant