学习React 的第五天 useContext共享数据

419 阅读3分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情

1. 简介

之前几天学习了React的组件创建,状态创建,父子组件传值等操作,今天的话就学习一个新的hook(useContext),并使用它进行非父子组件传递数据的一个操作

1.代码学习

1. Context

  1. 在之前的操作中只学习了父子组件的数据传递,如果想要爷孙组件,那么只能一层层的传递下去,就显得非常冗余,而且一旦组件需要更多从来自顶层组件的 props,你还得在中间层级一个一个加上去,这将会变得非常麻烦。
  2. Context 设计目的是为了共享那些“全局”的数据,例如当前认证的用户、主题或首选语言。
  3. 这个Hook 和 Vue的 provide / inject 功能一样,使用 Provider在顶层组件中提供数据,使用useContext在底层组件中获取数据。

2. 代码学习

  1. 先创建几个需要共享数据的组件
    1. App下使用的Main组件
    2. Main下使用的Footer组件,Header组件,再来一个公用组件Title组件
    3. 组件现在就是子孙级的组件,嵌套使用和一个公用。
        1. App组件
        function App() {
    
            return (
                    <Main/>
            )
        }
        2.  Main 组件
        function Main() {
            return <div>
                <Header/>
                <hr/>
                <div>
                    这是Main的Content
                </div>
                <hr/>
                <Footer/>
            </div>
        }
    
    1. Header 组件
    export function Header() {
        return <div>
            这是Header
        </div>
    }
    
    1. Footer组件
    export function Footer() {
        return <div>
            这是footer
    
        </div>
    }
    
    1. 创建Context 共享容器
    import {createContext, useContext, useState} from 'react'
    interface ContextType {
        id: string
        name: string
        getUser?: Function
    }
    
    const context = createContext<ContextType>({} as any)
    
    1. 在父组件中使用Provider提供数据
    function App() {
    
        const [user, SetUser] = useState({
            id: "1",
            name: "共享组件数据",
            getUser: () => {
                alert("获取用户")
            }
        })
    
    
        return (
            <context.Provider value={user}>
                <Main/>
            </context.Provider>
        )
    }
    
    1. 在子组件中使用数据

    通过 **const cot = useContext(context)**接收数据, 因为是ts可以直接通过先前定义好的属性名直接点读出

    function Main() {
        const cot = useContext(context)
    
        return <div>
            <Header/>
            <hr/>
            <div>
                这是Main的Content
                <p>{cot.name}</p>
                <p>{cot.id}</p>
            </div>
            <hr/>
            <Footer/>
        </div>
    }
    
    1. 接下来我们将在Header和Footer 中使用,会发现没有context对象,因为在当前文件中是直接使用定义好的context实例
    2. 在其他文件中想要使用的话我们可以把这个context对象拿出来
      1. 为context创建一个单独的文件
          import {createContext} from 'react'
      
          export interface ContextType {
              id: string
              name: string
          }
      
          export const context = createContext<ContextType>({} as any)
      
      1. 组件使用
      import {context} from '../UserContext'
      import {useContext} from 'react'
      
      export function Footer() {
          const cot = useContext(context)
      
          return <div>
              这是footer
              <p>{cot.id}</p>
              <p>{cot.name}</p>
          </div>
      }
      
      1. APP.tsx 文件使用
      import './App.css'
      import {Footer} from './component/Footer'
      import {Header} from './component/Header'
      
      import {context, ContextType} from './UserContext'
      import {useContext, useState} from 'react'
      
      
      function Main() {
          const cot = useContext(context)
      
          return <div>
              <Header/>
              <hr/>
              <div>
                  这是Main的Content
                  <p>{cot.name}</p>
                  <p>{cot.id}</p>
              </div>
              <hr/>
              <Footer/>
          </div>
      }
      
      
      function App() {
      
          const [user, SetUser] = useState<ContextType>({
              id: "123",
              name: "共享组件数据"
          })
      
      
          return (
              <context.Provider value={user}>
                  <Main/>
              </context.Provider>
          )
      }
      
      export default App
      
  2. 如果需要修改数据,也可以直接吧SetUser传递过去
      const [user, SetUser] = useState<ContextType>({
            id: "123",
            name: "共享组件数据"
        })
    
    
        return (
            <context.Provider value={{user, SetUser}}>
                <Main/>
            </context.Provider>
        )
    
  3. 接收方也需要结构赋值来接受
import {context} from '../context/UserContext'
import {useContext} from 'react'

export function Footer() {
    const {user, SetUser} = useContext(context)

    return <div>
        这是footer
        <p>{user.id}</p>
        <p>{user.name}</p>
        <button onClick={() => {SetUser({id: "2", name: "footer用户"})}}>
            通过Footer更改
        </button>
    </div>
}

3. 总结

  1. 学习了通过Context,进行跨组件传递数据。
  2. 也可以直接传递修改方法,进行数据修改,一处修改全局数据都会发生改变。