失常的 Increment 和 Decrement扭转 Display 的 count
import React, { useState } from 'react'function Display(props) {  return <h1>Counter value : {props.counter}</h1>}function Increment(props) {  return <button onClick={() => props.addToCounter(1)}>Increment</button>}function Decrement(props) {  return <button onClick={() => props.addToCounter(-1)}>Decrement</button>}function Index() {  const [counter, setCounter] = useState(0);  const addToCounter = value => setCounter(counter + value);  return (    <div>      <h1>Teste</h1>      <Display counter={counter} />      <Increment addToCounter={addToCounter} />      <Decrement addToCounter={addToCounter} />    </div>  )}export default Index
一步一步来改装
  • 应用useContext来替换Display组件中的props

    import React, { useState, useContext, createContext } from 'react'const CounterContext = createContext({counter: 0})function Display(props) {const context = useContext(CounterContext)return <h1>Counter value : {context.counter}</h1>}
  • 编写reducer去代替组件中的addToCounter办法

    import React, { useState, useContext, createContext, useReducer } from 'react'const CounterContext = createContext({counter: 0})function Display(props) {const context = useContext(CounterContext)return <h1>Counter value : {context.state.counter}</h1>}function Increment(props) {const context = useContext(CounterContext)return <button onClick={() => context.dispatch({  type: 'ADD_TO_COUNTER',  value: 1})}>Increment</button>}function Decrement(props) {const context = useContext(CounterContext)return <button onClick={() => context.dispatch({  type: 'ADD_TO_COUNTER',  value: -1})}>Decrement</button>}function Index() {const [state, dispatch] = useReducer((state, action) => {  switch (action.type) {    case 'ADD_TO_COUNTER':      return {        ...state,        counter: state.counter + action.value      }    default:      return state  }}, { counter: 0 })return (  <CounterContext.Provider value={{state, dispatch}}>    <h1>Teste</h1>    <Display />    <Increment />    <Decrement />  </CounterContext.Provider>)}export default Index
  • 把CounterContext.Provider抽成组件拿进去

    function CounterContextProvider(props) {const [state, dispatch] = useReducer((state, action) => {  switch (action.type) {    case 'ADD_TO_COUNTER':      return {        ...state,        counter: state.counter + action.value      }    default:      return state  }}, { counter: 0 })return (  <CounterContext.Provider value={{ state, dispatch }}>    {props.children}  </CounterContext.Provider>)}function Index() {return (  <CounterContextProvider>    <h1>Teste</h1>    <Display />    <Increment />    <Decrement />  </CounterContextProvider>)}
    把组件分一下文件就是

    index.jsx

    import React, { useState, useContext, createContext, useReducer } from 'react'import Display from '../components/ComB'import {Increment, Decrement} from '../components/ComA'export const CounterContext = createContext({counter: 0})function CounterContextProvider(props) {const [state, dispatch] = useReducer((state, action) => {  switch (action.type) {    case 'ADD_TO_COUNTER':      return {        ...state,        counter: state.counter + action.value      }    default:      return state  }}, { counter: 0 })return (  <CounterContext.Provider value={{ state, dispatch }}>    {props.children}  </CounterContext.Provider>)}function Index(props) {return (  <CounterContextProvider>    <h1>Teste</h1>    <Display />    <Increment />    <Decrement />  </CounterContextProvider>)}export default Index

    comA.jsx

    import React, { useContext } from "react"import { CounterContext } from '../pages/index.tsx'export function Increment(props) {const context = useContext(CounterContext)return <button onClick={() => context.dispatch({  type: 'ADD_TO_COUNTER',  value: 1})}>Increment</button>}export function Decrement(props) {const context = useContext(CounterContext)return <button onClick={() => context.dispatch({  type: 'ADD_TO_COUNTER',  value: -1})}>Decrement</button>}

    comB.jsx

    import React, {useContext} from 'react'import {CounterContext} from '../pages/index'function ComB() {const context = useContext(CounterContext)return <h1>Counter value : {context.state.counter}</h1>}export default ComB