Почему мое состояние не обновляется в redux при нажатии кнопки

#reactjs #typescript #redux

#reactjs #машинописный текст #сокращение

Вопрос:

Я пытаюсь обновить свое состояние redux, но, похоже, оно не обновляется при нажатии на кнопку. У меня есть выпадающий список «команды», и при нажатии кнопки «добавить команду» он должен обновляться со статическими данными «команда 1» и «команда 2», однако он не обновляется. Извиняюсь за объем кода, который я новичок в redux и понятия не имею, в чем может быть проблема. код ниже:

Store.ts

 import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk';

/* FILE DEPENDENCIES */
import RootReducer from './rootReducer';

//Fix dev tools
const Store = createStore(RootReducer, composeWithDevTools(applyMiddleware(thunk)));

export type RootStore = ReturnType<typeof RootReducer>;

export default Store;
 

teamsReducer.ts

 import { Team } from '../Models/TeamsModels';
import { TeamsDispatchTypes, TEAMS_FAIL, TEAMS_LOADING, TEAMS_SUCCESS } from './Actions/TeamsActionTypes';

export interface IDefaultState {
    loading: boolean;
    teams?: Team[];
}

const defaultState: IDefaultState = {
    loading: false,
};

const teamsReducer = (state: IDefaultState = defaultState, action: TeamsDispatchTypes): IDefaultState => {
    switch (action.type) {
        case TEAMS_FAIL:
            return {
                loading: false,
                teams: state.teams,
            };
        case TEAMS_LOADING:
            return {
                loading: true,
                teams: state.teams,
            };
        case TEAMS_SUCCESS:
            return {
                loading: false,
                teams: action.payload,
            };
        default:
            return state;
    }
};

export default teamsReducer;

 

TeamsActions.ts

 import { Dispatch } from 'redux';
import { Team } from '../../Models/TeamsModels';
/*FILE DEPENDENCIES*/
import { TeamsDispatchTypes, TEAMS_FAIL, TEAMS_SUCCESS } from './TeamsActionTypes';

export const GetTeams = () => (dispatch: Dispatch<TeamsDispatchTypes>) => {
    try {
        const newPayload: Team[] = [{ name: 'Team 1' }, { name: 'Team 2' }];

        dispatch({
            type: TEAMS_SUCCESS,
            payload: newPayload,
        });
    } catch (e) {
        dispatch({
            type: TEAMS_FAIL,
        });
    }
};
 

TeamActionTypes.ts

 import { Team } from '../../Models/TeamsModels';

export const TEAMS_LOADING = 'TEAMS_LOADING';
export const TEAMS_SUCCESS = 'TEAMS_SUCCESS';
export const TEAMS_FAIL = 'TEAMS_FAIL';

export interface TeamsLoading {
    type: typeof TEAMS_LOADING;
}

export interface TeamsSuccess {
    type: typeof TEAMS_SUCCESS;
    payload: Team[];
}

export interface TeamsFail {
    type: typeof TEAMS_FAIL;
}

export type TeamsDispatchTypes = TeamsLoading | TeamsFail | TeamsSuccess;
 

rootReducer.ts

 import { combineReducers } from 'redux';

/*FILE DEPENDENCIES*/
import TeamsReducer from './Teams/teamsReducer';

const RootReducer = combineReducers({
    teams: TeamsReducer,
});

export default RootReducer;
 

index.tsx

 import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './Component/App/App';
import reportWebVitals from './reportWebVitals';
import { Provider } from 'react-redux';
import Store from './State/Store';

ReactDOM.render(
    <Provider store={Store}>
        <App />
    </Provider>,
    document.getElementById('root'),
);

reportWebVitals();
 

App.tsx

 import React from 'react';
import Navbar from '../Navbar/Navbar';
import { BrowserRouter as Router, Switch } from 'react-router-dom';
import './App.css';

function App(): JSX.Element {
    return (
        <div className="App">
            <Router>
                <Navbar></Navbar>
                <Switch></Switch>
            </Router>
        </div>
    );
}

export default App;
 

Панель навигации.tsx

 import React from 'react';
import { NavLink } from 'react-router-dom';
import '../Navbar/Navbar.css';

import { RootStore } from '../../State/Store';
import { GetTeams } from '../../State/Teams/Actions/TeamsActions';
import { useDispatch, useSelector } from 'react-redux';

export default function Navbar(): JSX.Element {
    const dispatch = useDispatch();
    const teamsState = useSelector((state: RootStore) => state.teams);

    //Is not updating store, need to look at this
    const handleOnClick = () => {
        dispatch(GetTeams());
    };

    console.log('Teams State: ', teamsState);
    return (
        <nav className="navbar navbar-expand-lg navbar-light bg-light">
            <NavLink className="navbar-brand" to="/">
                Navbar
            </NavLink>
            <button
                className="navbar-toggler"
                type="button"
                data-toggle="collapse"
                data-target="#navbarNavDropdown"
                aria-controls="navbarNavDropdown"
                aria-expanded="false"
                aria-label="Toggle navigation"
            >
                <span className="navbar-toggler-icon"></span>
            </button>
            <div className="collapse navbar-collapse" id="navbarNavDropdown">
                <ul className="navbar-nav">
                    <li className="nav-item dropdown">
                        <a
                            className="nav-link dropdown-toggle"
                            href="#"
                            id="navbarDropdownMenuLink"
                            data-toggle="dropdown"
                            aria-haspopup="true"
                            aria-expanded="false"
                        >
                            Dropdown link
                        </a>
                        <div className="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                            <a className="dropdown-item" href="/add-team" onClick={handleOnClick}>
                                Add Team
                            </a>
                            {teamsState.teams amp;amp;
                                teamsState.teams.map((team) => (
                                    <a className="dropdown-item" href={'/'   team.name} key={team.name}>
                                        {team.name}
                                    </a>
                                ))}
                        </div>
                    </li>
                </ul>
            </div>
        </nav>
    );
}

 

Комментарии:

1. Я рекомендую вам добавить кучу консолей. регистрирует и определяет, где он не выполняется. Это бы нам очень помогло

2. В redux devtools вы можете узнать, какие действия отправляются и какие изменения они вносят в состояние. Это должно быть первое место для поиска, и при публикации вопроса это должна быть информация, добавленная к вашему вопросу.

Ответ №1:

Что происходит, так это то, что действие отправляется, и команды сохраняются в состоянии, но затем вся страница немедленно обновляется, и данные теряются. Это связано с тем, что ваша «Команда добавления» является a элементом с href тегом, поэтому нажатие на эту ссылку вызывает handleOnClick , но также вызывает навигацию. Поскольку вы используете только an a , а не a Link из react-router-dom , это событие навигации обрабатывается неправильно.

Команды начали появляться, как только я удалил href ссылку «Добавить команду», хотя это не очень хорошая практика a , если это не ссылка, поэтому вместо нее следует использовать a div или какой-либо другой HTML-элемент. При нажатии на имя отдельной команды по-прежнему возникает та же проблема с потерей данных из-за нажатия на a тег, поэтому вы захотите использовать Link там.