8

useReducer + useContext + createContext

 3 years ago
source link: https://segmentfault.com/a/1190000040329556
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

useReducer + useContext + createContext

发布于 39 分钟前
正常的 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

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK