React中的createContext和useContext

9,634

使用createContext的正确姿态

本文介绍一下 React 中常见的 Context APIclassHook中的使用方式。在使用 Context API 之前,我们还需要知道为啥要使用❓

引入Context的原因

考虑到组件有可能 层层嵌套 ,在传 props 的过程中,如果书写大量的 ...props,造成props数据混乱。

169724b4ef9d9ce7 (1).png

如何使用context

  • 首先要引入 React 内置的 React Context API 📦
  • 然后创建 provider
  • 最后创建 consumer 使用hook可以不用创建consumer

使用 createContext

// context.jsx
import React,{createContext,useState} from 'react'
export const demoContext = createContext({})
export const {Provider,Consumer } = demoContext;

const Context = () =>{
    
    const [name,setName] = useState('Mr.long');
    
    const handleNameClick = (params) => setName(params);
      
     const initValue ={
        name,
        handleNameClick
    }
    return <Provider value={initValue}>{props.children}</Provider>

}
export default Context

使用 Consumer 组件

consumer是从createContext函数的返回值导出。它是个render props模式组件。


// render Name 组件

import React from 'react'

export default  Render class extends React.Component{
    render(){
        return <div>
         <p>{props.name}</p>
         <button  onClick ={() => props.handleNameClick(props.name +'!')}>点击修改名</button>
       </div>
    }
}


// app.jsx
import {Context,Consumer} from './Context'
import React from 'react'
import RenderName from './renderName'
const App = () =>{

return <Context>
     <Consumer>
     {(value) =><RenderName {...value} />}
     </Consumer>
    </Context>
}

useContext

想在hook中使用Context可以借助useContext来使用,来看代码。

import React,{useContext} from 'react'
import {demoContext} from './context'
const HookContext =() =>{
    // useContext 传入的是createContext出来的实例 而不是他里面的组件 
    //这里的contextValue就能拿到值,不在需要Consumer 组件了
   const contextValue =  useContext(demoContext)
    return (
    <div>
      {contextValue.name}
      <button onClick={() => contextValue.handleNameClick(contextValue.name +'!')}>点击改变值</button>
    </div>
  );
}
export default HookContext

总结

使用Context可以避免的组件的层层props嵌套的问题。但是它使用consumer拿值时,会多一层组件。但得益于useContexthook我们可以不使用consumer组件。直接拿到值,直观。一般的使用场景,如那拿全局的class前缀,或者国际化,Ui主题颜色等。

当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。Provider 及其内部 consumer 组件都不受制于 shouldComponentUpdate 函数,因此当 consumer 组件在其祖先组件退出更新的情况下也能更新。