【问题标题】:Update state props without firing a dispatch() - React Redux在不触发 dispatch() 的情况下更新 state props - React Redux
【发布时间】:2020-10-23 12:09:23
【问题描述】:

我有一个模式,其中包含一个触发 HTTP 请求的按钮,此时显示的 html 将根据来自服务器的成功/错误响应而改变,其中响应会更改在 @987654322 中处理的状态道具@函数。

我现在遇到的问题是,当我关闭它时,我想将模式重置为其初始状态预请求。 我以前通过使用本地组件状态来完成此操作,但后来更新了使用上面显示的请求映射状态道具的功能。

我很好奇是否可以在不触发随机 URI 调度的情况下重置状态?

Component.jsx

const mapStatesToProps = ({myState}) => ({
    response: myState.response,
    success: !!(myState.success),
    fail: !!(myState.fail)
});

const mapDispatchToProps = dispatch => ({
    doReq: () => {
        dispatch(doMyRequest());
    }
});

class MyComponent extends Component {
    toggleModal = () => // modal toggle code

    render() {
        const {response, success, fail} = this.props;

        <div className="myModal">
            // Modal stuff here
            {!success && !fail && (
                <button onClick="() => toggleModal()">Close modal</button>
            )}
            {success && !fail && (
                <h1>Some success message</h1>
            )}
            {!success && fail && (
                <h1>Some fail message</h1>
            )}
        </div>
    }
}

req-actions.js

export const MY_REQUEST;
export const MY_REQUEST_SUCCESS;
export const MY_REQUEST_ERROR;

export const doMyRequest = () => ({
    type: MY_REQUEST,
    agent: agent.req.doRequest
})

req-reducer.js

import { deepEqual, deepClone } from '../McUtils';
import {
    MY_REQUEST,
    MY_REQUEST_ERROR,
    MY_REQUEST_SUCCESS
} from "../actions/req-actions";

export default (state = {}, action) => {
    let newState = deepClone(state);

    switch (action.type) {
        case MY_REQUEST:
            console.log('SENDING REQUEST');
            newState.response = null;
            newState.success = false;
            newState.fail = false;
            break;

        case MY_REQUEST_SUCCESS:
            console.log('SUCCESS');
            newState.response = action.payload;
            newState.success = true;
            newState.fail = false;
            break;

        case MY_REQUEST_ERROR:
            console.log('FAIL');
            newState.response = action.payload;
            newState.success = false;
            newState.fail = true;
            break;

        default:
            return state;
    }

    return newState;
}

【问题讨论】:

  • 不清楚您要的是什么。 modal 里面是什么,一个表单?
  • 与其在关闭模态时重置状态而不发送请求,不如将 draft 保持在模态的本地状态并仅将其保存到 redux传输成功后存储。只是因为应用程序使用了 redux,所以没有理由将每个中间状态存储在商店中。如果模态框包含一个表单,那么除非提交,否则表单状态可能应该是该表单的本地状态。 modal 应该是一个自己的组件,在打开时会从 store 中以初始状态安装。
  • 非常同意@trixn。 Redux 用于应用程序状态,而不是临时状态。这里是defined by flutter,但在反应中它是 100% 完全相同的东西。我无法告诉你在开发人员决定将所有内容放入redux而不是在适用时使用本地状态的应用程序上工作是多么令人抓狂。

标签: javascript reactjs redux react-redux


【解决方案1】:

只需使用另一个动作:

case MY_REQUEST_RESET:
   return {} // only putting {} in here because this is what you have defined your initialState to be according to your reducer.

个人偏好是这样清楚地定义你的初始状态。

const initialState = {};

export default (state = initialState, action) => {
    switch(action.type) {
       ... your existing handlers
       case MY_REQUEST_RESET:
          return initialState
    }
}

接线:

const mapDispatchToProps = dispatch => ({
    doReq: () => {
        dispatch(doMyRequest()),
    },
    reset: () => {
        dispatch(resetMyRequest());
    }
});


// types
const MY_REQUEST_RESET = 'MY_REQUEST_RESET';

// action creator (may be referred to as "actions")
const resetMyRequest = () => ({ type: MY_REQUEST_RESET })

编辑:当我在这里时,这真的很恶心:

let newState = deepClone(state);

并带有“我真的不知道自己在做什么”的恶臭,并可能导致性能问题。您正在深度克隆通过 redux 触发的每个操作的状态,即使这些操作不是这个 reducer 感兴趣的操作。

如果你在reducer中改变状态,只改变你关心的部分,不要改变“全部”。

例如

export default (state = {}, action) => {
    switch (action.type) {
        case MY_REQUEST:
            console.log('SENDING REQUEST');
            return {
                success: false,
                fail: false,
                response: null
            }

        case MY_REQUEST_SUCCESS:
            console.log('SUCCESS');
            return {
                ...state, // this will contain "fail: false" already
                success: true,
                response: action.payload
            };

        case MY_REQUEST_ERROR:
            console.log('FAIL');
            return {
                ...state, // this will contain "success: false" already
                error: true,
                response: action.payload
            };

        default:
            return state;
    }

【讨论】:

  • 关于新的Action,这将如何连接?只是想如果我正在创建一个新的调度:dispatch(resetMyModal()),它将执行我的操作,格式如req-actions.js 中所示 - 我是否忽略了agent,因为我没有发送实际要求?如上所示,我在reducer 部分制作了新案例。我对actions 有点困惑
  • @physicsboy - 在我的答案中添加接线部分。
  • 啊哈!惊人的!以为没用,但是好像我不小心删除了另一个动作XD至于您(Trixn)的其他建议,我知道您的意思。拾取已建立的代码库有问题,是吗?将在某个时候考虑摆脱 deepClone。也许是技术债务。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 2016-10-17
  • 2017-10-20
  • 2018-09-03
  • 2020-05-13
  • 2016-08-30
相关资源
最近更新 更多