我忙于一些概念验证,基本上要求在用户尚未登录时使主页成为登录屏幕,然后在状态更改时显示具有相关内容的组件。成功认证后。
我必须事先声明我是个新手,可以做出反应并进行还原,并且正忙于完成教程以提高自己的技能。但是,本教程有点基础,因为它不需要处理与服务器的连接即可完成工作。
我的第一个问题是在then
的最后一个fetch
的上下文中获得道具,因为我遇到了this.props.dispatch
未定义的错误。我使用了旧的javascript技巧,如果在最后的console.log
中放了then
,则可以看到它不再是未定义的,而是实际上按预期的功能。
对我来说,现在的问题是,调用dispatch
时什么也没发生。但是,如果我手动刷新页面,它将填充AuthenticatedPartialPage
,因为localstorage
已填充。
我的理解是,在调用dispatch
时,将重新评估条件语句,并显示AuthenticatedPartialPage
。
感觉dispatch
没有将更改传达回父组件,因此似乎什么都没发生。这是正确的吗?如果是这样,我将如何连接那段代码?
主页HOC:
import React from 'react';
import { createStore, combineReducers } from 'redux';
import { connect } from 'react-redux';
import AuthenticatedPartialPage from './partials/home-page/authenticated';
import AnonymousPartialPage from './partials/home-page/anonymous';
import { loggedIntoApi, logOutOfApi } from '../actions/authentication';
import authReducer from '../reducers/authentication'
// unconnected stateless react component
const HomePage = (props) => (
<div>
{ !props.auth
? <AnonymousPartialPage />
: <AuthenticatedPartialPage /> }
</div>
);
const mapStateToProps = (state) => {
const store = createStore(
combineReducers({
auth: authReducer
})
);
// When the user logs in, in the Anonymous component, the local storage is set with the response
// of the API when the log in attempt was successful.
const storageAuth = JSON.parse(localStorage.getItem('auth'));
if(storageAuth !== null) {
// Clear auth state in case local storage has been cleaned and thus the user should not be logged in.
store.dispatch(logOutOfApi());
// Make sure the auth info in local storage is contained in the state.auth object.
store.dispatch(loggedIntoApi(...storageAuth))
}
return {
auth: state.auth && state.auth.jwt && storageAuth === null
? state.auth
: storageAuth
};
}
export default connect(mapStateToProps)(HomePage);
其中匿名LOC为:
import React from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { loggedIntoApi } from '../../../actions/authentication';
export class AnonymousPartialPage extends React.Component {
constructor(props) {
super(props);
}
onSubmit = (e) => {
e.preventDefault();
const loginData = { ... };
// This is where I thought the problem initially occurred as I
// would get an error that `this.props` was undefined in the final
// then` of the `fetch`. After doing this, however, the error went
// away and I can see that `props.dispatch is no longer undefined
// when using it. Now though, nothing happens.
const props = this.props;
fetch('https://.../api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(loginData)
})
.then(function(response) {
return response.json();
})
.then(function(data) {
if(data && data.jwt) {
props.dispatch(loggedIntoApi(data));
localStorage.setItem('auth', JSON.stringify(data));
}
// else show an error on screen
});
};
render() {
return (
<div>
... onSubmit gets called successfully somewhere in here ...
</div>
);
}
}
export default connect()(AnonymousPartialPage);
动作:
// LOGGED_INTO_API
export const loggedIntoApi = (auth_token) => ({
type: 'LOGGED_INTO_API',
auth: auth_token
});
// LOGGED_OUT_OF_API
export const logOutOfApi = (j) => ({
type: 'LOG_OUT_OF_API'
});
最后是减速器:
const authDefaultState = { };
export default (state = authDefaultState, action) => {
switch (action.type) {
case 'LOGGED_INTO_API':
// SOLUTION : changed this line "return action.auth;" to this:
return { ...action.auth, time_stamp: new Date().getTime() }
case 'LOG_OUT_OF_API':
return { auth: authDefaultState };
default:
return state;
}
};
答案 0 :(得分:1)
我的建议是确保您在Redux中更改的状态正在更改根据javascript的相等运算符!。对于发布的另一个捕捉这个想法here的问题,确实有一个很好的答案。基本上,您不能对旧对象进行变异并将其发送回Redux,并希望它会重新呈现,因为与旧对象的相等性检查将返回TRUE,因此Redux认为没有任何改变!我必须通过使用更新后的值创建一个全新的对象并通过dispatch()将其发送来解决此问题。
本质上:
x = {
foo:bar
}
x.foo = "baz"
dispatch(thereWasAChange(x)) // doesn't update because the x_old === x returns TRUE!
相反,我创建了一个新对象:
x = {
foo:"bar"
}
y = JSON.parse(JSON.stringify(x)) // creates an entirely new object
dispatch(thereWasAChange(y)) // now it should update x correctly and trigger a rerender
// BE CAREFUL OF THE FOLLOWING!
y = x
dispatch(thereWasAChange(y)) // This WON'T work!!, both y and x reference the SAME OBJECT! and therefore will not trigger a rerender
希望这会有所帮助!