Реагировать не обнаруживая обновления в магазине Redux - PullRequest
0 голосов
/ 10 февраля 2020

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

interface Account {
    username: string | null;
    isLoggedIn: boolean;
    role: string | null;
}

const accountReducer = (state: Account, action: any): Account | {} => {
    switch (action.type) {
        case "SET_ACCOUNT":
            return {
                username: action.payload.username,
                isLoggedIn: action.payload.isLoggedIn,
                role: action.payload.role,
            };

        case "LOGOUT_ACCOUNT":
            return {
                username: null,
                isLoggedIn: false,
                role: null,
            };

        default:
            return { ...state };
    }
};

export default accountReducer;
interface Account {
    username: string | null;
    isLoggedIn: boolean;
    role: string | null;
}

const setAccount = (account: Account) => {
    return {
        type: "SET_ACCOUNT",
        payload: account,
    };
};

const logoutAccount = () => {
    return {
        type: "LOGOUT_ACCOUNT",
        payload: {
            username: null,
            isLoggedIn: false,
            role: null,
        },
    };
};

export default { setAccount, logoutAccount };

И у меня есть кнопка выхода из системы, которая вызывает следующую функцию:

const logoutUser = async (): Promise<void> => {
        await axios({
            method: "POST",
            url: API.logout,
            withCredentials: true,
            headers: {
                "X-CSRF-TOKEN": csrf.token,
            },
        });
        dispatch(allActions.accountActions.logoutAccount());
    };

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

Вот пример одного из моих компонентов, который необходимо обновить:

import React from "react";
import { NavLink, Link } from "react-router-dom";
import { useSelector } from "react-redux";

import "../../css/Navbar.css";
import LoggedInDiv from "../account/LoggedInDiv";
import LoginRegisterDiv from "../account/LoginRegisterDiv";

const Navbar: React.FC = () => {
    const account = useSelector((state: any) => state.accountReducer);

    return (
        <div className="main-navbar-container">
            <div className="navbar-logo-container">
                <h1 style={{ padding: "0px", margin: "0px" }}>
                    <Link to="/" className="navbar-link">
                       Logo
                    </Link>
                </h1>
            </div>
            <div style={{ display: "flex", flexDirection: "column" }}>
                <div className="navbar-links-container">
                    <NavLink to="/builder" className="navbar-link" activeClassName="navbar-link-active">
                        Builder
                    </NavLink>
                    <NavLink
                        to="/finishedbuilds"
                        className="navbar-link"
                        activeClassName="navbar-link-active"
                    >
                        Finished Builds
                    </NavLink>
                    <NavLink to="/about" className="navbar-link" activeClassName="navbar-link-active">
                        About
                    </NavLink>
                    <NavLink to="/user/login" className="navbar-link" activeClassName="navbar-link-active">
                        Contact
                    </NavLink>
                </div>
                <div style={{ marginLeft: "21px", marginTop: "6px" }}>
                    <div className="account-container">
                        {account.isLoggedIn ? (
                            <LoggedInDiv username={account.username} />
                        ) : (
                            <LoginRegisterDiv />
                        )}
                    </div>
                </div>
            </div>
        </div>
    );
};

export default Navbar;

Хорошо, поэтому я наконец-то нашел проблему. Мой топор ios POST-запрос к /logout фактически возвращал ошибку и сбой, поэтому я даже не получил dispatch после запроса. Я просто завернул код ax ios в блок try catch, пока не выяснил, почему мой бэкэнд выдает ошибки при попытке выйти из системы, даже если он успешно выходит из системы.

Ответы [ 2 ]

0 голосов
/ 10 февраля 2020

Хорошо, так что я наконец нашел проблему. Мой запрос ios POST для /logout фактически возвращал ошибку и сбой, поэтому я даже не получил dispatch после запроса. Я просто завернул код ax ios в блок try catch, пока не выяснил, почему мой бэкэнд выдает ошибки при попытке выйти из системы, даже если он успешно выходит из системы.

0 голосов
/ 10 февраля 2020

Прежде всего, вы всегда должны устанавливать свое состояние в начальное состояние

const INITIAL_STATE = {
    username: null,
    isLoggedIn: false,
    role: null
}

А затем в своем редукторе вы устанавливаете его на state: Account = INITIAL_STATE

Это предотвращает ваш магазин от возврата undefined до его заполнения.

Хорошей практикой также является использование константных типов для ваших действий, чтобы избежать неправильного наложения их в редукторе или действии.

Когда дело доходит до компоненты не обновляются, я подозреваю, что компоненты не правильно подключены к хранилищу с избыточностью, и если они не получают уведомления об изменении хранилища (например, новые реквизиты или изменение локального состояния), они не будут повторно отображаться .

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

Редактировать:

const Navbar: React.FC = (props) => {
    const account = props.account;

    return ( your code );

};

const mapStateToProps = (state: any) => {
    return state.accountReducer;
};

export default connect(mapStateToProps)(Navbar);
...