注意:hooks只能在函数(无状态组件)中使用
createContext:一个创建上下文函数,执行产生一个上下文对象,包含两个属性,Provider组件和Consumer组件
Provider:用来包裹整合组件,传递一个value属性,把context上下文注入到整个组件当中
Consumer组件,在里面使用函数调用Provider的value传递的值成形参,并取出使用
import React, {
useReducer, useContext, createContext, Context } from 'react';
//初始化stroe的类型、初始化值、reducer
const ADD_COUNTER = 'ADD_COUNTER';
const initialReucer = {
count: 100
}
function reducer(state: typeof initialReucer, action: {
type: typeof ADD_COUNTER }) {
switch (action.type) {
case ADD_COUNTER:
return {
...state, count: state.count + 1 }
default:
return state;
}
}
const ProviderContext: Context<any> = createContext('provider');//创建上下文实例
//高阶组件,给函数组件注入上下文
const providerHoc = (reducer: Function, initialState: any) => (Com: React.FC<any>) => {
return () => {
const [state, dispatch] = useReducer<any>(reducer, initialState);
return (
<ProviderContext.Provider value={
{
state, dispatch }}>
<Com />
</ProviderContext.Provider >
);
}
}
function Test(): JSX.Element {
const {
state, dispatch } = useContext(ProviderContext);//通过ProviderContext这个上下文实例获取到value,解构出
console.log(state);
return (
<>
<h2>{
state.count}</h2>
{
/*使用dispatch分发action,触发reducer返回新的state*/}
<button onClick={
() => dispatch({
type: ADD_COUNTER })}>++</button>
</>
);
}
export default providerHoc(reducer, initialReucer)(Test);//注入reducer,initialReucer到Test组件中,通过高阶组件对Test组件进行包裹注入
//stroe.tsx
import React, {
useReducer, createContext, Context } from 'react';
const ADD_COUNTER = 'ADD_COUNTER';//action-type的类型
export const addActions =()=> ({
type: ADD_COUNTER });//创建一个同步action
export const initialReucer = {
//初始化的state
count: 100
} // state的类型,action的类型
export function reducer(state: typeof initialReucer, action: {
type: typeof ADD_COUNTER }) {
switch (action.type) {
case ADD_COUNTER:
return {
...state, count: state.count + 1 }
default:
return state;
}
}
export const ProviderContext: Context<any> = createContext('provider');//创建上下文实例
//高阶组件,给函数组件注入上下文
export const providerHoc = (reducer: Function, initialState: any) => (Com: React.FC<any>) => {
return () => {
const [state, dispatch] = useReducer<any>(reducer, initialState);
return (
<ProviderContext.Provider value={
{
state, dispatch }}>
<Com />
</ProviderContext.Provider >
);
}
}
import React, {
useContext } from 'react';
import {
ProviderContext, addActions, providerHoc, reducer, initialReucer } from './store';
function Test(): JSX.Element {
const {
state, dispatch } = useContext(ProviderContext);//通过ProviderContext这个上下文实例获取到value,解构出
console.log(state);
return (
<>
<h2>{
state.count}</h2>
<button onClick={
() => dispatch(addActions())}>++</button>
</>
);
}
export default providerHoc(reducer, initialReucer)(Test);//注入reducer,initialReucer到Test组件中,通过高阶组件对Test组件进行包裹注入
import React, {
useReducer, createContext, Context, Dispatch } from 'react';
const ADD_COUNTER = 'ADD_COUNTER';
const addActions = () => ({
type: ADD_COUNTER });//创建一个同步action
// 创建一个异步action的函数,返回一个action对象
const asyncAction = (dispatch: Dispatch<any>) => {
return {
asyncAddaction() {
//这是一个异步的添加action,定时器模拟异步
console.log('执行addActions之前,发送请求 : ' + Date.now());//打印一下时间
setTimeout(() => {
console.log('执行addActions ,请求后: ' + Date.now());
dispatch(addActions());//执行同步action
}, 1000);
}
}
}
export const initialReucer = {
count: 100
}
export function reducer(state: typeof initialReucer, action: {
type: typeof ADD_COUNTER }) {
switch (action.type) {
case ADD_COUNTER:
return {
...state, count: state.count + 1 }
default:
return state;
}
}
export const ProviderContext: Context<any> = createContext('provider');//创建上下文实例
//高阶组件,给函数组件注入上下文
export const providerHoc = (reducer: Function, initialState: any) => (Com: React.FC<any>) => {
return () => {
const [state, dispatch] = useReducer<any>(reducer, initialState);
const asyncActions: any = asyncAction(dispatch);//对dispatch进行注入包裹,然后返回
return (
<ProviderContext.Provider value={
{
state, asyncActions }}>
<Com />
</ProviderContext.Provider >
);
}
}
import React, {
useContext } from 'react';
import {
ProviderContext, providerHoc, reducer, initialReucer } from './store';
function Test(): JSX.Element {
const {
state, asyncActions } = useContext(ProviderContext);//通过ProviderContext这个上下文实例获取到value,解构出
const {
asyncAddaction } = asyncActions;//取出asyncAddaction
console.log(state);
return (
<>
<h2>{
state.count}</h2>
<button onClick={
() => asyncAddaction()}>++</button>
</>
);
}
export default providerHoc(reducer, initialReucer)(Test);//注入reducer,initialReucer到Test组件中,通过高阶组件对Test组件进行包裹注入
这样一个简单的异步redux模拟就成功了,相比之下,不用使用redux就是一个很好的实例
还有整合多个reducer的案例,就看另外一个博客把:
模拟redux的combineReducers函数合并reducer,使用createContext, useContext, useReducer整合多个reducer案例(点击跳转到)
npm i redux-custom --save 下载这个小型整合多个reducer的库
其它React进阶用法和hooks的个人使用见解:
React进阶用法和hooks的个人使用见解:
1.lazy+Suspense懒加载的使用
2.hooks的useState、useEffect、自定义钩子的实际使用
3.useCallback+useMemo+memo性能优化
5.useRef,useImperativeHandle和forwardRef的结合使用以及useLayoutEffect、useDebugValue的简单使用