组件中的 Redux 存储不是最新的已更新
Redux store not up to date in component did update
我有一个用于用户登录的 React 容器。当它挂载时,它会获取一些第三方脚本并将它们注入页面(这会创建一个登录小部件)
登录阶段分为两部分,第一部分是登录第三方系统,完成后我需要使用第一个系统的payload登录第二个系统。
在 componentDidMount
我发出了获取第三方脚本的请求,这里一切正常。
当我点击登录按钮时(它是第三方提供的预构建小部件,可以触发我们可以挂钩的回调,无需自己创建小部件等),回调将触发,我们得到客户令牌回来了,这里一切都很好。
我在使用该客户令牌时遇到问题的部分,我使用 redux 将其添加到商店中,在 componentDidUpdate
然后我根据当前道具检查 prevProps 以检查令牌,如果它存在我触发一个操作来登录到第二个系统。我想避免多次触发此操作,所以一旦我将 hasRequested
字段添加到商店,然后在 componentDidUpdate
中检查它以防止它被多次调用。
这个位不起作用,因为我在页面上有多个 LoginContainer
实例,componentDidUpdate
触发多次并且商店没有及时更新hasRequested
值,结果是我最终发出了多个 API 请求。
有人知道我如何拥有一个容器的多个实例,但在其道具更新时限制动作触发的次数吗?
下面的示例代码
登录容器
class LoginContainer extends Component {
/**
* componentDidMount
*/
componentDidMount () {
if (!this.props.thirdPartyCode.hasRequested) {
this.props.fetchThirdPartySriptsAndLoad();
}
}
/**
* componentDidUpdate
*/
componentDidUpdate (prevProps) {
if (
prevProps.authentication.customerToken !== this.props.authentication.customerToken
&& !this.props.authentication.hasRequested
) {
this.props.authenticateUserWithSecondSystem();
}
}
认证减速器
import {
SECOND_SYSTEM_AUTHENTICATE_REQUEST,
SECOND_SYSTEM_AUTHENTICATE_SUCCESS,
SECOND_SYSTEM_AUTHENTICATE_FAILURE,
} from 'actions/authentication/authentication-actions';
export const defaultState = {
isFetching: false,
hasRequested: false,
error: '',
customerToken: ''
};
/**
* Reducer for authentication
* @param {Object} state
* @param {Object} action
* @returns {Object} updated state
*/
export default function (state = defaultState, action) {
switch (action.type) {
case SECOND_SYSTEM_AUTHENTICATE_REQUEST:
return Object.assign({}, state, {
isFetching: true,
hasRequested: true
});
case SECOND_SYSTEM_AUTHENTICATE_SUCCESS:
return Object.assign({}, state, {
isFetching: false
});
身份验证操作
export const SECOND_SYSTEM_AUTHENTICATE_REQUEST = 'SECOND_SYSTEM_AUTHENTICATE_REQUEST';
export const SECOND_SYSTEM_AUTHENTICATE_SUCCESS = 'SECOND_SYSTEM_AUTHENTICATE_SUCCESS';
export const SECOND_SYSTEM_AUTHENTICATE_FAILURE = 'SECOND_SYSTEM_AUTHENTICATE_FAILURE';
/**
* Request Authenticate
* @returns {{type: string}}
*/
function requestSecondSystemAuthentication () {
return {
type: SECOND_SYSTEM_AUTHENTICATE_REQUEST
};
}
/**
* Authenticate Success
* @param {Object} data - response data
* @returns {{type: string}}
*/
function secondSystemAuthenticateSuccess (data) {
return {
type: SECOND_SYSTEM_AUTHENTICATE_SUCCESS,
data
};
}
/**
* Post Authenticate
* @returns {Function} - action creator
*/
export function authenticateUserWithSecondSystem (authenticationToken) {
return dispatch => {
dispatch(requestSecondSystemAuthentication());
ApiService.post('/api/authenticate', authenticationToken)
.then(payload => dispatch(secondSystemAuthenticateSuccess(payload)))
}
最后我决定我试图让它变得太复杂,我选择了一个名为 authenticateUser
的动作,它在点击时被调用并处理登录到第一个提供者的逻辑和然后是第二个。
我有一个用于用户登录的 React 容器。当它挂载时,它会获取一些第三方脚本并将它们注入页面(这会创建一个登录小部件)
登录阶段分为两部分,第一部分是登录第三方系统,完成后我需要使用第一个系统的payload登录第二个系统。
在 componentDidMount
我发出了获取第三方脚本的请求,这里一切正常。
当我点击登录按钮时(它是第三方提供的预构建小部件,可以触发我们可以挂钩的回调,无需自己创建小部件等),回调将触发,我们得到客户令牌回来了,这里一切都很好。
我在使用该客户令牌时遇到问题的部分,我使用 redux 将其添加到商店中,在 componentDidUpdate
然后我根据当前道具检查 prevProps 以检查令牌,如果它存在我触发一个操作来登录到第二个系统。我想避免多次触发此操作,所以一旦我将 hasRequested
字段添加到商店,然后在 componentDidUpdate
中检查它以防止它被多次调用。
这个位不起作用,因为我在页面上有多个 LoginContainer
实例,componentDidUpdate
触发多次并且商店没有及时更新hasRequested
值,结果是我最终发出了多个 API 请求。
有人知道我如何拥有一个容器的多个实例,但在其道具更新时限制动作触发的次数吗?
下面的示例代码
登录容器
class LoginContainer extends Component {
/**
* componentDidMount
*/
componentDidMount () {
if (!this.props.thirdPartyCode.hasRequested) {
this.props.fetchThirdPartySriptsAndLoad();
}
}
/**
* componentDidUpdate
*/
componentDidUpdate (prevProps) {
if (
prevProps.authentication.customerToken !== this.props.authentication.customerToken
&& !this.props.authentication.hasRequested
) {
this.props.authenticateUserWithSecondSystem();
}
}
认证减速器
import {
SECOND_SYSTEM_AUTHENTICATE_REQUEST,
SECOND_SYSTEM_AUTHENTICATE_SUCCESS,
SECOND_SYSTEM_AUTHENTICATE_FAILURE,
} from 'actions/authentication/authentication-actions';
export const defaultState = {
isFetching: false,
hasRequested: false,
error: '',
customerToken: ''
};
/**
* Reducer for authentication
* @param {Object} state
* @param {Object} action
* @returns {Object} updated state
*/
export default function (state = defaultState, action) {
switch (action.type) {
case SECOND_SYSTEM_AUTHENTICATE_REQUEST:
return Object.assign({}, state, {
isFetching: true,
hasRequested: true
});
case SECOND_SYSTEM_AUTHENTICATE_SUCCESS:
return Object.assign({}, state, {
isFetching: false
});
身份验证操作
export const SECOND_SYSTEM_AUTHENTICATE_REQUEST = 'SECOND_SYSTEM_AUTHENTICATE_REQUEST';
export const SECOND_SYSTEM_AUTHENTICATE_SUCCESS = 'SECOND_SYSTEM_AUTHENTICATE_SUCCESS';
export const SECOND_SYSTEM_AUTHENTICATE_FAILURE = 'SECOND_SYSTEM_AUTHENTICATE_FAILURE';
/**
* Request Authenticate
* @returns {{type: string}}
*/
function requestSecondSystemAuthentication () {
return {
type: SECOND_SYSTEM_AUTHENTICATE_REQUEST
};
}
/**
* Authenticate Success
* @param {Object} data - response data
* @returns {{type: string}}
*/
function secondSystemAuthenticateSuccess (data) {
return {
type: SECOND_SYSTEM_AUTHENTICATE_SUCCESS,
data
};
}
/**
* Post Authenticate
* @returns {Function} - action creator
*/
export function authenticateUserWithSecondSystem (authenticationToken) {
return dispatch => {
dispatch(requestSecondSystemAuthentication());
ApiService.post('/api/authenticate', authenticationToken)
.then(payload => dispatch(secondSystemAuthenticateSuccess(payload)))
}
最后我决定我试图让它变得太复杂,我选择了一个名为 authenticateUser
的动作,它在点击时被调用并处理登录到第一个提供者的逻辑和然后是第二个。