useReducer ReactJS hook 的 2 个用例

2025-05-25

useReducer ReactJS hook 的 2 个用例

useReducer是一个 Hook,它使我们能够更高效地管理多个状态,创建复杂的状态逻辑,以及管理依赖于先前状态的状态。以下两个用例很好地展示了如何使用此 Hook。

useReducer用例

  • 管理多个状态:修改数组
  • 修改复杂状态,例如数组或对象:登录表单

管理多个状态

useReducer可以用来简化多个状态对数据的影响。在这种情况下,添加、移除和清除数组的操作可以通过使用useReducer而不是 3 个单独的状态来实现。

import { useReducer } from "react";

const myReducer = (prevState, action) => {
    let array;
    switch (action.type) {
        case 'ADD':
            array = [...prevState];
            array.push(action.payload);
            return array;
        case 'REMOVE':
            array = [...prevState];
            array.pop();
            return array;
        case 'CLEAR':
            return prevState = [];
        default:
            break;
    }
};

const UseCaseMultipleStates = props => {
    const [state, dispatcher] = useReducer(myReducer, ['initial value']);
    console.log(state);

    // Three different state triggers
    const addHandler = () => {
        dispatcher({ type: 'ADD', payload: Math.round((Math.random() * 100 + 100)) });
    };
    const removeHandler = () => {
        dispatcher({ type: 'REMOVE' });
    };
    const clearHandler = () => {
        dispatcher({ type: 'CLEAR' });
    };

    return (
        <>
            <hr />
            <h2>useReducer use case</h2>
            <h3>Manage multiple states: modify an array</h3>
            <button onClick={addHandler}>[+] Add random value to array</button>
            <button style={{ margin: "0 2rem" }} onClick={removeHandler}>[-] Remove last value from array</button>
            <button onClick={clearHandler}>[x] Clear array</button>
            <p>Shopping cart array:</p>
            <p><b>{state.length === 0 && '(empty)'}{state.join(' - ')}</b></p>
        </>
    );
};

export default UseCaseMultipleStates;
Enter fullscreen mode Exit fullscreen mode

修改复杂状态,例如数组或对象:登录表单

useReducer在处理多种状态和复杂的状态逻辑时尤其方便。

通过用这个钩子而不是多个钩子来处理登录表单,useState我们可以体会到这个钩子的强大之处。

用于模拟登录 API 的辅助函数(感谢Harry Wolff提供此代码):

export async function loginHelper({ username, password }) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (username === 'user' && password === 'password') {
                resolve();
            } else {
                reject();
            }
        }, 1000);
    });
}
Enter fullscreen mode Exit fullscreen mode

主要成分:

import { useReducer } from "react";
import { loginHelper } from "./loginHelper";

const myReducer = (prevState, action) => {
    switch (action.type) {
        case 'USERNAME':
            return {
                ...prevState,
                username: action.payload,
            };
        case 'PASSWORD':
            return {
                ...prevState,
                password: action.payload,
            };
        case 'LOGGED_IN':
            return {
                ...prevState,
                isLoggedIn: true,
            };
        case 'LOGGED_OUT':
            return {
                ...prevState,
                isLoggedIn: false,
                username: '',
                password: '',
            };
        case 'IS_LOADING':
            return {
                ...prevState,
                isLoading: true,
            };
        case 'IS_NOT_LOADING':
            return {
                ...prevState,
                isLoading: false,
            };
        case 'ERROR':
            return {
                ...prevState,
                isError: true,
                isLoading: false,
            };

        default:
            break;
    }
};

const initialState = {
    username: '',
    password: '',
    isLoggedIn: false,
    isLoading: false,
    isError: false,
};

const UseCaseComplexStates = props => {
    const [state, dispatcher] = useReducer(myReducer, initialState);

    const usernameHandler = e => {
        dispatcher({ type: 'USERNAME', payload: e.target.value });
    };

    const passwordHandler = e => {
        dispatcher({ type: 'PASSWORD', payload: e.target.value });
    };

    const logoutHandler = e => {
        dispatcher({ type: 'LOGGED_OUT' });
    };

    const submitHandler = async e => {
        e.preventDefault();

        // Check credentials (simulated)
        try {
            dispatcher({ type: 'IS_LOADING' });
            await loginHelper({ username: state.username, password: state.password });
            dispatcher({ type: 'IS_NOT_LOADING' });
            dispatcher({ type: 'LOGGED_IN' });
        } catch {
            dispatcher({ type: 'ERROR' });
            alert('🚨 Incorrect username or password');
        }
    };

    return (
        <>
            <hr />
            <h2>useReducer use case</h2>
            <h3>Modify complex states, such as arrays or objects: login form</h3>
            <div style={{ maxWidth: '50%', backgroundColor: '#a8dadc', borderRadius: '1rem', padding: '2rem' }}>
                {state.isLoggedIn
                    ? <><p>Welcome!</p><button onClick={logoutHandler}>Log out!</button></>
                    : <form onSubmit={submitHandler}>
                        <div style={{ margin: '1rem 0' }}>
                            <label htmlFor="username">Username</label>
                            <input type="text" id="username" onChange={usernameHandler} value={state.username} style={{ margin: '0 1rem' }} placeholder='user' />
                        </div>
                        <div style={{ margin: '1rem 0' }}>
                            <label htmlFor="password">Password</label>
                            <input type="password" id="password" onChange={passwordHandler} value={state.password} style={{ margin: '0 1rem' }} placeholder='password' />
                        </div>
                        <div style={{ margin: '1rem 0' }}>
                            <button type="submit" disabled={state.isLoading}>{state.isLoading ? 'Logging you in...' : 'Log in'}</button>
                        </div>

                    </form>
                }
            </div>
        </>
    );
};

export default UseCaseComplexStates;
Enter fullscreen mode Exit fullscreen mode

您可以在此处实时观看所有这些示例

您还可以查看此存储库中的代码。

文章来源:https://dev.to/colocodes/2-use-cases-of-the-usereducer-reactjs-hook-ine
PREV
如何调试 React 应用
NEXT
使用 Mern 开发约会应用简介先决条件概述