失常的 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