gpt4 book ai didi

reactjs - 我必须在 Redux Reducer 中返回状态吗?

转载 作者:行者123 更新时间:2023-12-04 01:23:13 25 4
gpt4 key购买 nike

我很难理解 redux-reducer 在 JavaScript 中的工作方式。

这是我正在使用的示例:

const intitialState = {
profile: null,
profiles: [],
repos: [],
loading: true,
error: {},
};

export default function (state = intitialState, action) {
const { type, payload } = action;

switch (type) {
case GET_PROFILE:
return {
...state,
profile: payload,
loading: false,
};
case PROFILE_ERROR:
return {
...state,
error: payload,
loading: false,
};
default:
return state;
}
}

关于这个 reducer ,这些假设中哪一个是正确的(如果有的话)?

A) 当 GET_PROFILE 被触发时,它返回 '...state' 作为初始状态,以便 redux 开发工具可以比较状态。

B)当 GET_PROFILE 被触发时,它实际上只是将值填充到我没有明确列出的对象中。在返回中看起来真的是这样的:
return {
profiles: profiles,
repos: repos,
error: error,
profile: payload,
loading: false,
};

如果 A 或 B 为真,那么如果我不返回 ...state 作为第一个会发生什么,这会弄乱其他对象吗?

编辑:它到底返回到哪里?

最佳答案

我会说B是真的。
如果不返回该状态,则该未返回状态的数据将丢失。

函数createStore给你一个带有 5 core functions 的 store 对象.
我认为从商店返回的以下 3 个函数是最值得注意的:

  • 订阅 function - 用于订阅商店。此函数返回 unsubscribe退订功能。
  • 如果您使用 react-redux ,这个订阅/取消订阅逻辑是
    已经使用 connect 在后台处理函数或useSelector钩。

  • 获取状态 函数 - 用于获取当前状态。
  • 如果您使用 react-redux这也在 connect 内部处理。函数或 useSelector钩。

  • 调度函数 - 用于更新全局状态。
  • 如果您使用 react-redux这是在 connect 内部处理的。
    函数或 useDispatch钩。


  • 不从 reducer 返回状态副本将导致您丢失未返回的状态。要了解原因,查看商店的 dispatch 会有所帮助。功能。

    店内 dispatch函数,你会看到一个 currentState变量是 reassigned从 reducer (或组合 reducer )返回的任何内容。 getState来自商店的功能 simply returns这个 currentState多变的。当前状态总是从此 getState 中检索。功能。

    因此,当您调度一个操作时,您的状态树将使用您从 reducer 返回的任何内容进行更新。

    这是一个小的 vanilla 示例,说明当您从 redux reducer 返回状态时与不返回任何状态时会发生什么。
    您可以运行并重新运行该代码段。蓝色按钮调度 GET_PROFILE带有返回状态的副本。黄色按钮调度一个 Action GET_PROFILE_NO_STATE_COPY_RETURNED返回与 GET_PROFILE 相同的对象没有状态副本 ...state .
    实际上,一旦你点击 GET_PROFILE_NO_STATE_COPY_RETURNED ,您将需要再次重新运行该代码段,因为未指定的状态属性已完全消失 :)
    redux 状态会使用 reducer 返回的任何内容进行更新。
    我使用了您问题中的 reducer :

    const createStore = (reducer, preloadedState, enhancer) => {
    if (typeof enhancer !== 'undefined') {
    return enhancer(createStore)(reducer, preloadedState);
    }
    let currentState = preloadedState;
    let listeners = [];

    const getState = () => currentState;

    const subscribe = listener => {
    listeners.push(listener);
    return () => {
    listeners = listeners.filter(l => l !== listener);
    };
    };

    // The returned from the reducer
    // inside the dispatch function
    // will be the new state.
    // https://github.com/reduxjs/redux/blob/master/src/createStore.ts#L246
    const dispatch = action => {
    currentState = reducer(currentState, action);
    listeners.forEach(l => l());
    };

    // initialize state
    dispatch({});

    return {
    getState,
    subscribe,
    dispatch,
    };
    };

    const initialState = {
    profile: null,
    profiles: [],
    repos: [],
    loading: true,
    error: {},
    };

    // action type constants
    const GET_PROFILE = 'GET_PROFILE';
    const PROFILE_ERROR = 'PROFILE_ERROR';
    const GET_PROFILE_NO_STATE_COPY_RETURNED = 'GET_PROFILE_NO_STATE_COPY_RETURNED';

    // reducer
    const reducer = (state = initialState, {
    type,
    payload
    }) => {
    switch (type) {
    case GET_PROFILE:
    return {
    ...state,
    profile: payload,
    loading: false,
    };
    case GET_PROFILE_NO_STATE_COPY_RETURNED:
    return {
    profile: payload,
    loading: false,
    };
    case PROFILE_ERROR:
    return {
    ...state,
    error: payload,
    loading: false,
    };
    default:
    return state;
    }
    };

    const store = createStore(reducer);

    const render = () => {
    const html = `
    <p>State</p>
    <pre><code>${JSON.stringify(store.getState(), null, 4)}</code></pre>
    `;
    document.getElementById('app').innerHTML = html;
    };

    store.subscribe(render);

    render();

    document.getElementById('get-profile').addEventListener('click', () => {
    const firstName = document.getElementById('firstName').value;
    const lastName = document.getElementById('lastName').value;
    store.dispatch({
    type: GET_PROFILE,
    payload: {
    firstName,
    lastName,
    },
    });
    });

    document
    .getElementById('get-profile-no-state-returned')
    .addEventListener('click', () => {
    const firstName = document.getElementById('firstName').value;
    const lastName = document.getElementById('lastName').value;
    store.dispatch({
    type: GET_PROFILE_NO_STATE_COPY_RETURNED,
    payload: {
    firstName,
    lastName,
    },
    });
    });
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet" />

    <div id="app"></div>

    <input class="form-control" id="firstName" placeholder="firstName" />
    <input class="form-control" id="lastName" placeholder="lastName" />
    <button class="btn btn-primary" id="get-profile">GET_PROFILE </button>
    <button class="btn btn-warning" id="get-profile-no-state-returned">GET_PROFILE_NO_STATE_COPY_RETURNED</button>


    因此,当您调度一个 Action 时,reducer 的返回值将成为您的新状态。
  • 引用 source code .
  • 关于reactjs - 我必须在 Redux Reducer 中返回状态吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62313003/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com