react context引起刷新的问题.

不使用context通信,传递setState通过props,memo包括进行浅比较前后props相同,两个子组件不会点击引起对方刷新:

const Count=memo((props)=>{
  console.log('count')
  const {count,setState}=props
  //const {setState}=useContext(MyContext)
  const fn=()=>{
     setState(v=>{return {...v,count:count+1}})
  }
  return <p onClick={fn}>{count}</p>
})
const Num=memo((props)=>{
  console.log('num')
  const {num,setState}=props
  //const {setState}=useContext(MyContext)
  const fn=()=>{
    setState(v=>{return {...v,num:num+1}})
  }
  return <p onClick={fn}>{num}</p>
})
const App=()=>{
  const [state,setState]=useState({count:0,num:1})
  return <div>
         <Count count={state.count} setState={setState}/>
         <Num num={state.num} setState={setState}/>
         </div>
}

const app = document.getElementById("app");
ReactDOM.render(<App/>, app)

使用context通信,传递setState,点击fn都会引起对方刷新,这样该怎样传递才能避免不必要刷新,子组件是什么前后改变了造成刷新:

const MyContext=createContext()
const MyProvider=MyContext.Provider
const Count=memo((props)=>{
  console.log('count')
  const {count}=props
  const {setState}=useContext(MyContext)
  const fn=()=>{
     setState(v=>{return {...v,count:count+1}})
  }
  return <p onClick={fn}>{count}</p>
})
const Num=memo((props)=>{
  console.log('num')
  const {num}=props
  const {setState}=useContext(MyContext)
  const fn=()=>{
    setState(v=>{return {...v,num:num+1}})
  }
  return <p onClick={fn}>{num}</p>
})
const App=()=>{
  const [state,setState]=useState({count:0,num:1})
  return <MyProvider value={{setState}}>
         <Count count={state.count}/>
         <Num num={state.num}/>
         </MyProvider>
}

const app = document.getElementById("app");
ReactDOM.render(<App/>, app)
阅读 5.6k
2 个回答
新手上路,请多包涵

context 引起的渲染不能被 memo 阻止,可以把真正的组件包一层当作 context 的子组件,再把值通过 props 传入真正的组件,这样真正的组件可以使用 memo 优化渲染。

import React, { useCallback } from 'react'

const MyContext = createContext({
  state: {
    count: 0,
    num: 1,  
  },
  setState: () => {},
})
const MyProvider = MyContext.Provider

const Count = React.memo((props) {
    return <p onClick={props.onClick}>{props.count}</p>
})

const CountWrapper = () => {
  console.log('count')
  
  const { state, setState } = useContext(MyContext)
  
  const fn = useCallback(() => {
    setState(v => ({
      ...v,
      count: state.count + 1,
    }))
  }, [])
  
  return <Count onClick={fn} count={state.count} />
})

cosnt Num = React.memo((props) => {
  return <p onClick={props.onClick}>{props.num}</p>
})

const NumWrapper = () => {
  console.log('num')
  
  const { state, setState } = useContext(MyContext)
  
  const fn = useCallback(() => {
    setState(v => ({
        ...v,
        num: state.num + 1,
      })
    )
  }, [])
  
  return <Num onClick={fn} num={state.num} />
}

const App = () => {
  const [state, setState] = useState({ count: 0, num: 1 })
  
  return (
    <MyProvider value={{ state, setState }}>
       <CountWrapper />
       <NumWrapper />
    </MyProvider>
   )
}

const app = document.getElementById("app");
ReactDOM.render(<App/>, app)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题