开发者问题收集

为什么 React 组件没有从 Redux 返回当前数据?

2021-05-09
374

我有一个与 redux 连接的 React 应用。该组件有一个表单,当表单提交时,它会对 api 进行 PUT 调用。当我提交表单时,我可以看到 redux 会相应地更新,但是当我尝试在我的组件中将 redux 状态作为 prop 访问时,props 数据不会返回当前数据并且关闭了 1。例如,这是我的 redux 存储中的数据:

Redux 存储:

redux store

当我在组件中执行 console.log("THIS PROPS: ", this.props) 时,我看到它 accountError 显示为 null

在此处输入图片说明

当我第二次再次分派动作时,只有那时我才看到我正在从 props 中的 redux 获取数据:

在此处输入图片说明

这是我拥有的代码目前:

OrgAccount.js

import { registerOrgAccount, getListOfOrgsAndAccts } from "../../store/actions";

handleSubmit = () => {
  this.props.registerOrgAccount(this.state)
  console.log("THIS PROPS: ", this.props)
  if(this.props.accountError === null) {
    this.toggleTab(this.state.activeTab + 1);
  }
};

<Link
  to="#"
  className="btn w-lg"
  onClick={() => {
    if (this.state.activeTab === 1) {
      this.handleSubmit();
    }
  }}
>
  Next
</Link>

const mapStatetoProps = (state) => {
  const { accounts, accountError, loading } = state.OrgAccount;
  return { accounts, accountError, loading };
};

const mapDispatchToProps = (dispatch) => {
  return {
      getListOfOrgsAndAccts: () => {
        dispatch(getListOfOrgsAndAccts())
    },
     registerOrgAccount: (data) => {
        dispatch(registerOrgAccount(data))
     },
     
  }
}

export default connect(mapStatetoProps, mapDispatchToProps)(OrgAccount);

Reducer:

const initialState = {
    accountError: null, accountsError: null, message: null, loading: null
}

const orgAccount = (state = initialState, action) => {
    switch (action.type) {
        case REGISTER_ORG_ACCOUNT:
            state = {
                ...state,
                account: null,
                loading: true,
                // accountError: null
            }
            break;
       
        case REGISTER_ORG_ACCOUNT_SUCCESSFUL:
            state = {
                ...state,
                account: action.payload,
                loading: false,
                accountError: null
            }
            break;
        case REGISTER_ORG_ACCOUNT_FAILED:
            state = {
                ...state,
                loading: false,
                accountError: action.payload ? action.payload.response : null
            }
            break;
        ...
        default:
            state = { ...state };
            break;
    }
    return state;
}

export default orgAccount;

Action

export const registerOrgAccount = (account) => {
    return {
        type: REGISTER_ORG_ACCOUNT,
        payload: { account }
    }
}

export const registerOrgAccountSuccessful = (account) => {
    return {
        type: REGISTER_ORG_ACCOUNT_SUCCESSFUL,
        payload: account
    }
}

export const registerOrgAccountFailed = (error) => {
    return {
        type: REGISTER_ORG_ACCOUNT_FAILED,
        payload: error
    }
}

Saga.js

import { registerOrgAccountSuccessful, registerOrgAccountFailed, getListOfOrgsAndAcctsSuccessful, getListOfOrgsAndAcctsFailed } from './actions';
import { putOrgAccount } from '../../../helpers/auth_helper';

function* registerOrgAccount({ payload: { account } }) {
    try {
        const response = yield call(putOrgAccount, {
            orgId: account.orgId,
            accountNumber: account.accountNumber,
            accountName: account.accountName,
            accountCode: account.accountCode,
            urlLink: account.urlLink,
            location: account.location,
            accountType: account.accountType,
            address: account.address,
            city: account.city,
            state: account.state,
            zip: account.zip,
            country: account.country,
            email: account.email,
            eula: "blah"
        });
        yield put(registerOrgAccountSuccessful(response));
    } catch (error) {
        yield put(registerOrgAccountFailed(error));
    }
}
1个回答

为了理解这里的根本原因,我认为了解一点关于不变性和 React 如何重新渲染的知识会有所帮助。简而言之,React 会在检测到引用更改时重新渲染。这就是为什么改变 prop 不会触发重新渲染的原因。

考虑到这一点,在您调用 handleSubmit 时, this.props.accountError 只是对内存中某个值的引用。当您分派操作并且状态更新时,将创建一个新的引用,这将触发组件的重新渲染。但是,传递给元素的 handleSubmit 函数仍然引用旧的 this.props.accountError,这就是它仍然为空的原因。

您可以通过在 componentDidUpdate 生命周期方法中实现检查来解决这个问题。例如像这样:

componentDidUpdate(prevProps) {
  if (prevProps.accountError === null && this.props.accountError !== null) {
    this.toggleTab(this.state.activeTab + 1)
  }
}
Stephan Olsen
2021-05-09