The correct development posture of react+typescript is to use the useReducer of hooks correctly

Correct useReducer in react+typescript project

We add a component Counter to the Home page to save a value count to record the number of times the button is clicked, as follows:

// Counter.tsx
import React, {
    
     useReducer } from 'react'

type StateType = {
    
    
    count: number;
}

type ActionType = {
    
    
    type: string;
    payload: number;
}

const initialState = {
    
    count: 0}

function countReducer(state: StateType, action: ActionType) {
    
    
    switch (action.type) {
    
    
        case 'increment':
            return {
    
    count: state.count + action.payload}
            break;
        case 'decrement':
            return {
    
    count: state.count - action.payload}
            break;
        default:
            return state
            break;
    }
}

export default function Counter() {
    
    
    const [state, dispatch] = useReducer(countReducer, initialState)

    const _increment = () => {
    
    
        dispatch({
    
    
            type: 'increment',
            payload: 1
        })
    }

    const _decrement = () => {
    
    
        dispatch({
    
    
            type: 'decrement',
            payload: 1
        })
    }

    return (
        <div>
            <p>Your count is {
    
    state.count}</p>
            <button onClick={
    
    _increment}>increment</button>&nbsp;&nbsp;
            <button onClick={
    
    _decrement}>decrement</button>
        </div>
    )
}

Use it on the Home page as follows:

// Home.tsx
import React from "react";
import Counter from "../components/Counter";

const Home = () => {
    
    
    return (
        <div>
            <p>这是Home页面</p>
            <Counter />
        </div>
    )
}

export default Home;

If we now add a new type of action, which is the reset button reset, that is, <button onClick={_reset}>reset</button>the
reducer function must also make corresponding changes, and the processing when adding a new type:

case 'reset':
	return initialState
	break;

The corresponding reset function is:

const _reset = () => {
    
    
	dispatch({
    
    
		type: 'reset'
	})
}

After writing this way, there will be a problem, that is, we _resetwill report an error when calling the function, because we only pass in a type parameter and no payload, the ts compiler will tell us that the type does not match here, but the function of our function is heavy setting, that is, there is no need to use the parameter payload at all, so what should I do? We can write ActionType like this:

type UpdateActionType = {
    
    
    type: 'increment' | 'decrement';
    payload: number;
}

type ResetActionType = {
    
    
    type: 'reset';
}

type ActionType = UpdateActionType | ResetActionType;

In this way, we will match the corresponding types when we increase, decrease, and reset, and the ts compiler can also play happily.
The complete code is as follows:

// Counter.tsx
import React, {
    
     useReducer } from 'react'

type StateType = {
    
    
    count: number;
}

type UpdateActionType = {
    
    
    type: 'increment' | 'decrement';
    payload: number;
}

type ResetActionType = {
    
    
    type: 'reset';
}

type ActionType = UpdateActionType | ResetActionType;

const initialState = {
    
    count: 0}

function countReducer(state: StateType, action: ActionType) {
    
    
    switch (action.type) {
    
    
        case 'increment':
            return {
    
    count: state.count + action.payload}
            break;
        case 'decrement':
            return {
    
    count: state.count - action.payload}
            break;
        case 'reset':
            return initialState
            break;
    }
}

export default function Counter() {
    
    
    const [state, dispatch] = useReducer(countReducer, initialState)

    const _increment = () => {
    
    
        dispatch({
    
    
            type: 'increment',
            payload: 1
        })
    }

    const _decrement = () => {
    
    
        dispatch({
    
    
            type: 'decrement',
            payload: 1
        })
    }

    const _reset = () => {
    
    
        dispatch({
    
    
            type: 'reset'
        })
    }

    return (
        <div>
            <p>Your count is {
    
    state.count}</p>
            <button onClick={
    
    _increment}>increment</button>&nbsp;&nbsp;
            <button onClick={
    
    _decrement}>decrement</button>&nbsp;&nbsp;
            <button onClick={
    
    _reset}>reset</button>
        </div>
    )
}

Code address and file path

Note:
The github warehouse address of the code in this article: Correctly use the useReducer file path in ts
: src/components/Counter.tsx.

Guess you like

Origin blog.csdn.net/weixin_40920953/article/details/122637300