React-Redux перерисовывает при отправке внутри HOC не работает - PullRequest
0 голосов
/ 09 сентября 2018

Я занят небольшим подтверждением концепции, где в основном требуется, чтобы домашняя страница была экраном входа в систему, когда пользователь еще не вошел в систему, после чего вместо этого отображается компонент с соответствующим содержимым при изменении состояния после успешной аутентификации.

Я должен заявить заранее, что я очень новичок в реагировании и сокращении и занят работой над учебником, чтобы улучшить свои навыки. Тем не менее, этот учебник является немного базовым в том смысле, что он не имеет отношения к соединению с сервером, чтобы выполнить работу на нем.

Моя первая проблема состояла в том, чтобы получить доступ к реквизиту в контексте последнего 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;
  }
};

1 Ответ

0 голосов
/ 09 сентября 2018

Я бы хотел убедиться, что состояние, которое вы изменяете внутри Redux, меняется в соответствии с оператором равенства javascript! . Есть действительно хороший ответ на другой опубликованный вопрос, который отражает эту идею здесь . По сути, вы не можете изменить старый объект и отправить его обратно в 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

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...