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
运行效果: 如果传多个值,可以设置为数组或者对象来传递。
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
运行效果: