Реакция + редукция. При отправке события в редуктор. оба редуктора получают одинаковые данные - PullRequest
0 голосов
/ 17 января 2019

Я недавно начал использовать избыточность для нового личного проекта.Это работало довольно хорошо, пока я не начал использовать «Объединение редукторов».Всякий раз, когда я нажимаю «Получить задачи», обновляются и мой пользователь, и мой редуктор задач, и хотя у них разные имена полей данных, оба получают одинаковые данные.Теперь я, вероятно, сделал некоторую неправильную инкапсуляцию здесь.Но независимо от того, как часто я просматривал документы, я просто не вижу, что делаю неправильно.

Мой скрипт инициализации магазина:

import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';

import toDoReducer from './todos/reducer';
import userReducer from './users/reducer';

const rootReducer = combineReducers({
    todosSlice: toDoReducer,
    usersSlice: userReducer
});

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(rootReducer, composeEnhancers(applyMiddleware(thunk)));

export default store;

вставляется в индекс:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './containers/app/App';
import * as serviceWorker from './serviceWorker';
import { Provider } from 'react-redux';

import configureStore  from './store/configureStore';

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

serviceWorker.unregister();

Мое приложение содержит логику для контейнера todo

import React, { Component } from 'react';
import { connect } from 'react-redux';

import * as todoActions from '../../store/todos/actions';
import UserContainer from '../usersContainer/UserContainer';

class App extends Component {

  componentDidMount() {
    console.log(this.props);
  }

  render() {
    let loading = '';
    let error = '';
    let todos = [];

    // check whether the component is fetching data
    this.props.loading === true ? loading = <p>Loading...</p> : loading = '';

    // check if there was an error
    this.props.error  && this.props.loading === false ? error = <p>There was an error</p> : error = '';

    // map the todos in the desired html markup.
    todos = this.props.todos.map( todo => {
      return <div key={todo.id}>  name: {todo.title} </div>
    });

    return (
      <div className="App">

        {/* <UserContainer /> */}

        {loading}
        {error}

        <p onClick={() => this.props.onFetchTodos()}>Fetch Todos</p>

        {todos}
      </div>
    );
  }
}


const mapStateToProps = state => {
  return {
    error: state.todosSlice.error,
    loading: state.todosSlice.loading,
    todos: state.todosSlice.todos
  }
}

const mapDispatchToProps = dispatch => {
  return {
    onFetchTodos: () => dispatch(todoActions.fetchTodos())
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(App);

, которое выполняет следующие действия:

import axios from 'axios';
export const FETCH_TODOS = 'FETCH_TODOS';
export const GET_TODOS_STARTED = 'GET_TODOS_STARTED';
export const FETCH_TODOS_SUCCESS = 'FETCH_TODOS_SUCCESS';
export const FETCH_TODOS_FAILURE = 'FETCH_TODOS_FAILURE';

export const fetchRequest = () => {
    return dispatch => {

        dispatch(getTodoStarted());

        axios.get('https://one365-api-dev.azurewebsites.net/api/teams/')
            .then(result => {
                dispatch(fetchTodosSucces(result));
            }).catch(error => {
                dispatch(fetchTodoFailure(error));
            });
    }

}

const getTodoStarted = () => ({
    type: GET_TODOS_STARTED
});

const fetchTodosSucces = todos => ({
    type: FETCH_TODOS_SUCCESS,
    payload: {
      ...todos
    }
});

const fetchTodoFailure = error => ({
    type: FETCH_TODOS_FAILURE,
    payload: {
      error
    }
});

export const fetchTodos = () => {
    return (dispatch => {
        dispatch(fetchRequest());
    });
}

И его редуктор

import * as actions from './actions';

const initialState = {
    error: null,
    loading: false,
    todos: []
}

const todosReducer = (state = initialState, action) => {

    switch(action.type) {

        case actions.GET_TODOS_STARTED: {
            console.log('fetch todo state', state)

            return {
                ...state,
                loading: state.loading = true
            };
        }

        case actions.FETCH_TODOS_SUCCESS: {
            const todos = action.payload.data;
            return {
                ...state,
                loading: false,
                todos: state.todos = todos
            };
        }

        case actions.FETCH_TODOS_FAILURE: {
            const error = action.payload.error;

            return {
                ...state,
                loading: false,
                error: state.error = error
            };
        }

        default: {
            return state;
        }
    }
}

export default todosReducer;

Компонент Users

    import React from 'react';
    import { connect } from 'react-redux';

    import * as userActions from '../../store/users/actions';

    class UserContainer extends React.Component {

        render () {
            let loading = '';
            let error = '';
            let users = [];

            // check whether the component is fetching data
            this.props.usersLoading === true ? loading = <p>Loading...</p> : loading = '';

            // check if there was an error
            this.props.usersError  && this.props.loading === false ? error = <p>There was an error</p> : error = '';

            // map the users in the desired html markup.
            users = this.props.users.map( user => {
              return <div key={user.id}>  name: {user.title} </div>
            });

            return (
              <div className="Users">

                {loading}
                {error}

                <p onClick={() => this.props.onFetchUsers()}>Fetch Users</p>

                {users}
              </div>
            );
        }
    }

    const mapStateToProps = state => {
        return {
            usersError: state.usersSlice.error,
            usersLoading: state.usersSlice.loading,
            users: state.usersSlice.users
        }
    }

    const mapDispatchToProps= (dispatch) => {
        return {
            onFetchUsers: () => dispatch(userActions.fetchUsers())
        }    
    }

    export default connect(mapStateToProps, mapDispatchToProps)(UserContainer);

the user actions:
import axios from 'axios';
export const FETCH_USERS = 'FETCH_TODOS';
export const FETCH_USERS_STARTED = 'GET_TODOS_STARTED';
export const FETCH_USERS_SUCCESS = 'FETCH_TODOS_SUCCESS';
export const FETCH_USERS_FAILURE = 'FETCH_TODOS_FAILURE';


export const fetchRequest = () => {
    return dispatch => {
        dispatch(fetchUsersStarted());

        axios.get('https://one365-api-dev.azurewebsites.net/api/me')
            .then(result => {
                dispatch(fetchUsersSuccess(result));
            }).catch(error => {
                dispatch(fetchUsersFailure(error));
            });
    }
}


export const fetchUsersSuccess = (users) => {
    return {
        type: FETCH_USERS_SUCCESS,
        payload: {
            ...users
        }
    }
}

export const fetchUsersStarted = () => ({
    type: FETCH_USERS_STARTED
});

export const fetchUsersFailure = (error) => {
    return {
        type: FETCH_USERS_FAILURE,
        payload: {
            error
        }
    }
}



export const fetchUsers = () => {
    return dispatch =>  {
        dispatch(fetchRequest()) 
    }
};

И его редуктор:

import * as actions from './actions';

const initialState = {
    error: '',
    loading: false,
    users: []
}

const userReducer = (state = initialState, action) => {

    switch(action.type) {

        case actions.FETCH_USERS_STARTED:  {
            console.log('fetch users state', state)
            return {
                ...state,
                loading: state.loading = true
            }
        } 

        case actions.FETCH_USERS_SUCCESS: {
            const users = action.payload.data;
            return {
                ...state,
                loading: false,
                users: state.users = users
            }
        }

        case actions.FETCH_USERS_FAILURE: {
            const error = state.payload.error;
            return {
                ...state,
                loading: false,
                error: state.error = error    
            }
        }

        default: {
            return state;
        }
    }

}


export default userReducer;

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

После того, как инструменты разработки приложения load redux отображают состояние следующим образом: enter image description here

, но как только я нажимаю на значок задачиобработчик.И задачи, и пользователи заполняются.enter image description here

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

1 Ответ

0 голосов
/ 17 января 2019

У вас есть проблема с копированием / вставкой. Вы изменили имена констант для ваших действий «USERS», но оставили значения такими же, как действия «TODOS».

export const FETCH_USERS = 'FETCH_TODOS';
export const FETCH_USERS_STARTED = 'GET_TODOS_STARTED';
export const FETCH_USERS_SUCCESS = 'FETCH_TODOS_SUCCESS';
export const FETCH_USERS_FAILURE = 'FETCH_TODOS_FAILURE';

Полагаю, вы хотели иметь:

export const FETCH_USERS = 'FETCH_USERS';
export const FETCH_USERS_STARTED = 'FETCH_USERS_STARTED';
export const FETCH_USERS_SUCCESS = 'FETCH_USERS_SUCCESS';
export const FETCH_USERS_FAILURE = 'FETCH_USERS_FAILURE';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...