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