最近在自学React,学到了它的一个集中状态管理工具Mobx。在使用Mobx进行数据传递的过程中,对Store进行模块化时,用到了React的context 这个API,用于导出统一的useStore方法给业务组件使用。
前引
Mobx中使用context进行模块统一导出,代码如下:
1. 定义task模块
//store/taskStore.js
import { makeAutoObservable } from 'mobx'
class TaskStore {
taskList = []
constructor() {
makeAutoObservable(this)
}
addTask () {
this.taskList.push('vue', 'react')
}
}
const task = new TaskStore()
export default task
2. 定义counterStore
//store/counterStore.js
import { makeAutoObservable } from 'mobx'
class CounterStore {
count = 0
list = [1, 2, 3, 4, 5, 6]
constructor() {
makeAutoObservable(this)
}
addCount = () => {
this.count++
}
changeList = () => {
this.list.push(7, 8, 9)
}
get filterList () {
return this.list.filter(item => item > 4)
}
}
const counter = new CounterStore()
export default counter
3. 组合模块导出统一方法
//store/index.js
import React from 'react'
import counter from './counterStore'
import task from './taskStore'
class RootStore {
constructor() {
this.counterStore = counter
this.taskStore = task
}
}
//实例化操作
const rootStore = new RootStore()
//使用React context机制 完成统一封装 Provider value = {传递的数据}
// context机制的数据查找链 Provider如果找不到 就找createContext方法执行时传入的参数
const context = React.createContext(rootStore)
//通过useContext拿到rootStore实例对象,然后返回
//只要在业务组件中,调用useStore() -> rootStore
const useStore = () => React.useContext(context)
// useStore() => rootStore { counterStore, taskStore }
export { useStore }
4. 组件使用模块中的数据
//app.jsx
import { observer } from 'mobx-react-lite'
// 导入方法
import { useStore } from './store'
function App() {
// 得到store
const store = useStore()
return (
<div className="App">
<button onClick={() => store.counterStore.addCount()}>
{store.counterStore.count}
</button>
</div>
)
}
// 包裹组件让视图响应数据变化
export default observer(App)
React中的context和provider是什么
在React中,Context是一种用于在组件树中共享数据的机制。它允许您在组件之间传递数据,而无需通过props手动传递。
Context由两个主要部分组成:
- Context对象:通过调用React.createContext()创建。这个函数返回一个Context对象,它包含了Provider和Consumer两个属性。Context对象用于定义共享数据的结构和默认值。
- Provider组件:Provider是Context对象的一个组件,用于向下层组件传递共享数据。它通过value属性接收数据,并将其传递给下层的Consumer组件。
使用Context,可以避免在组件层级中手动传递数据,特别是对于需要在多个组件之间共享的全局数据非常有用。它提供了一种在组件树中传递数据的方式,使得子组件可以轻松地访问共享数据。
为什么不用props而用context
通常来说,通过 props 将信息从父组件传递到子组件。但是:
- 如果必须通过许多中间组件向下传递 props
- 或在应用中的许多组件需要相同的信息
传递 props 会变的十分冗长和不便。Context 允许父组件向其下层无论多深的任何组件提供信息,而无需通过 props 显式传递。
Context传参和Provider传参的关系
context传参包含了provider传参。在React中,Context是这样传递参数的:
- 通过Provider传递参数
在使用Context时,可以在Context.Provider组件上的value属性来传递参数。这个参数可以是任何的javascript对象,数组,函数等。
//创建了一个名为`MyContext`的Context对象
//1. 通过createContext传入默认值
const MyContext = React.createContext('defalut value');
function App() {
const data = "Hello, Context!";
return (
//2. 通过context对象的provider value将data作为参数传入
<MyContext.Provider value={data}>
<ChildComponent />
</MyContext.Provider>
);
}
- 通过Consumer或useConetxt接收参数
使用Context.Consumer组件或useContext钩子可以在组件中接收Context提供的参数。
const MyContext = React.createContext();
function ChildComponent() {
return (
<MyContext.Consumer>
{value => <div>{value}</div>}
</MyContext.Consumer>
);
}
//或者使用useContext钩子:
const MyContext = React.createContext();
function ChildComponent() {
const value = useContext(MyContext);
return <div>{value}</div>;
}
//在ChildComponent组件中使用Context.Consumer组件或useContext钩子来接收Context提供的参数
useContext接收的参数有哪些,哪个优先级高
当使用Provider组件提供参数时,通过value属性传递的数据会成为当前组件及其所有子组件中可用的共享数据。
当使用useContext钩子来接收参数时,它会查找最近的上层Provider组件,并返回该Provider组件提供的值。
总之,优先级是根据组件树的结构来确定的。如果在组件树中有多个Provider组件,useContext钩子将返回最近的上层Provider组件提供的值。如果没有找到任何Provider组件,useContext将返回Context对象的默认值(在createContext时指定的默认值)。
import React,{ useContext } from 'react'
//通过createContext传入默认值
const MyContext = React.createContext('Default Value')
function App() {
const valueFromProvider = 'Value from Provider'
return (
//通过Provider value传参
<MyContext.Provider value={valueFromProvider}>
<ChildComponent />
</MyContext.Provider>
)
}
function ChildComponent() {
// context机制的数据查找链 Provider如果找不到 就找createContext方法执行时传入的参数
const valueFromContext = useContext(MyContext)
return (
<div>
<div>Value from Provider: {valueFromContext}</div>
</div>
)
}
export default App
//页面最终展示为Value from Provider:Value from Provider
初学小白,以上仅个人拙见,望不吝赐教