作者
JavaScript 是一种轻量级的脚本语言。所谓“脚本语言”(script language),指的是它不具备开发操作系统的能力,而是只用来编写控制其他大型应用程序(比如浏览器)的“脚本”。 JavaScript 只合适嵌入更大型的应用程序环境,去调用宿主环境提供的底层 API。 目前,已经嵌入 JavaScript 的宿主环境有多种,最常见的环境就是浏览器,另外还有服务器环境,也就是 Node 项目。
目录
怎么让useContext + useReduce ≈ redux
落霞与孤鹜齐飞 7月11日 17 1 2 17 1 2
正常的 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
扫码分享到移动端
2 条评论
sumicode_1123LV1 评论于 7月12日 10:27

老哥,看一下文章排版呀

落霞与孤鹜齐飞LV5 7月17日 17:14:

谢谢老哥,果然有两段代码没有被识别格式

参与评论互动
登录即可参与评论互动哦