Я занят небольшим подтверждением концепции, где в основном требуется, чтобы домашняя страница была экраном входа в систему, когда пользователь еще не вошел в систему, после чего вместо этого отображается компонент с соответствующим содержимым при изменении состояния после успешной аутентификации.
Я должен заявить заранее, что я очень новичок в реагировании и сокращении и занят работой над учебником, чтобы улучшить свои навыки. Тем не менее, этот учебник является немного базовым в том смысле, что он не имеет отношения к соединению с сервером, чтобы выполнить работу на нем.
Моя первая проблема состояла в том, чтобы получить доступ к реквизиту в контексте последнего 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;
}
};