useContext函数

通常来说,你会通过props将信息从父组件传递到子组件。但是,如果你必须通过许多中间组件向下传递props,或是在你应用中的许多组件需要相同的信息,传递props会变的十分冗长和不便。
Context允许父组件向其下层无论多深的任何组件提供信息,而无需通过props显式传递。

1. 多层组件传递数据

jsx
import { createContext, useContext, useState } from 'react'

function Title() {
  const value = useContext(Context)
  return (
    <div>
      <h3>Title组件</h3>
      {value}
    </div>
  )
}

function Head() {
  return (
    <>
      <h3>Head组件</h3>
      <Title/>
    </>
  )
}
// Context一定要使用大写,设置默认值
const Context = createContext(1)

function App() {
  const [num, setNum] = useState(0)
  const clickHandle = () => {
    setNum(num+1)
  }
  return (
    <div>
      <button onClick={clickHandle}>添加</button>
      <Context.Provider value={num}>
        <Head/>
      </Context.Provider>
    </div>
  )
}

export default App

运行效果:
Alt text 如果传多个值,可以设置为数组或者对象来传递。

2. 共享状态

Reducer可以整合组件的状态更新逻辑。Context可以将信息深入传递给其他组件。你可以组合使用它们来共同管理一个复杂页面的状态。也就是说前面的案例是爷孙组件进行数据通信,兄弟通信就需要共享状态。更复杂的状态管理,可以采用第三方库:Redux,Mobx,Zustand等

jsx
import ListContent from './ListContent.jsx'

import ListHead from './ListHead.jsx'

import ListProvider from './ListProvider.jsx'



function App() {



  return (

    <div>

      <ListProvider >

        <ListHead/>

        <ListContent/>

      </ListProvider>

    </div>

  )

}

export default App
jsx
import {ListContext, ListDispatchContext} from './ListProvider.jsx'

import { useContext } from 'react'



function ListContent() {

  const dataList = useContext(ListContext)

  const listDispatch = useContext(ListDispatchContext)

  return (

    <div>

      <ul>

        {

          dataList.map(item => {

            return (

              <li key={item.id}>

                {item.name}

                <button onClick={()=>listDispatch({type:'edit', id: item.id})}>修改</button>

                <button onClick={()=>listDispatch({type:'remove', id: item.id})}>删除</button>

              </li>

            )

          })

        }

      </ul>

    </div>

  )

}

export default ListContent;
jsx
import {ListDispatchContext} from './ListProvider.jsx'

import { useContext } from 'react'



function ListHead() {

  const listDispatch = useContext(ListDispatchContext)

  return (

    <div>

      <button onClick={() => listDispatch({type: 'add'})} >添加1</button>

    </div>

  )

}



export default ListHead
jsx
import {useReducer, createContext}  from 'react'

import { useImmerReducer } from 'use-immer'



export const ListContext = createContext()

export const ListDispatchContext = createContext()



function listReducer(draft, action) {

  // 其中action就是传值

  switch (action.type) {

    case 'add':

      draft.push({id:5, name:'baden'})

      break

    case 'remove':

      const data = draft.find(item => item.id === action.id)

      draft.splice(data, 1)

      break

    case 'edit':

      const editData = draft.find(item => item.id === action.id)

      editData.name = 'new'+editData.name

      break

  }

}





function ListProvider({children}) {

  const [list, listDispatch] = useImmerReducer(listReducer, [

    { id: 1, name: 'John' },

    { id: 2, name: 'Bob' },

    { id: 3, name: 'Mark' },

    { id: 4, name: 'Trump' }

  ])

  return (

    <ListContext.Provider value={list}>

      <ListDispatchContext.Provider value={listDispatch}>

        {children}

      </ListDispatchContext.Provider>

    </ListContext.Provider>

  )

}



export default ListProvider
运行效果: ![Alt text](/web/react/images/Snipaste_20241224_095839.png)

评论