【问题标题】:React Redux Load the list in the table after Adding an item with Async ApiReact Redux 使用 Async Api 添加项目后加载表中的列表
【发布时间】:2018-09-19 10:02:01
【问题描述】:

我正在尝试学习 React / Redux 并使用 .Net core Api 作为后端服务来构建简单的应用程序。

我的要求

  1. 当用户点击保存按钮时添加项目

  2. 重定向到List页面,再次加载数据,检索新添加的数据

  3. 我必须重新加载数据,不能只在列表中追加新项目,因为我需要获取刚刚生成的新添加项目的 keyId

所以,我在我的操作文件中链接承诺,以便在 AddItem 成功后调用 LoadItems。

如果我不链接这些承诺,我将无法在列表页面中看到新创建的项目。重定向到 '/todo' 发生得如此之快,甚至在之前 AddItem() 尚未完成。如果我为重定向添加 2 秒延迟,我可以看到新项目。

操作

export const addTodoItemSuccess = todoItem => ({ type: actionTypes.ADD_TODO_ITEM_SUCCESS, payload: todoItem });

export const loadTodoItemsSuccess = items => ({ type: actionTypes.LOAD_TODO_SUCCESS, payload: items });

export const loadTodoItems = () => {
    return function (dispatch) {
        return TodoService.getAll().then(items => {
            dispatch(loadTodoItemsSuccess(items));
        });
    };
}

export const addTodoItem = (item) => {
    return function (dispatch) {
        return TodoService.add(item).then(() => {
            return TodoService.getAll().then(items => {
                dispatch(loadTodoItemsSuccess(items));
            });
        });
    };
}

减速器

import * as actionTypes from '../actions/actionTypes';

const todoReducer = (state = [], action) => {
    switch (action.type) {
        case actionTypes.LOAD_TODO_SUCCESS:
            return action.payload;
        default:
            return state;
    }
}

export default todoReducer;

AddTodoPage 容器

submitNewTodo = event => {
        event.preventDefault();     
        this.props.addTodoItem(this.state.item);

        //redirect to Todo List Page after saving
        this.context.router.history.push(`/todo`); 
    }

TodoListPage 容器

componentDidMount = () => {
        this.props.dispatch(loadTodoItems());
    }

它按预期工作,我可以在列表中看到新项目。但问题是它正在向 Api 发送 TWO GetAll() 查询。 第一个调用来自 Actions.js,第二个调用来自 TodoListPage.js 中的componentDidMount

如果我从 componentDidMount 中删除了 loadTodoItems(),当我导航到 TodoListPage '/todo' 时,我无法查看任何项目,因为这些项目尚未加载。

在教程中,他们通常在index.js 中执行store.dispatch(loadTodoItems()); 以使其可用。即使在用户尚未导航到该页面(查找数据除外)之前,我也觉得加载数据是错误的。

您能否建议我实现上述要求的最佳方法是什么?我不想调用 Api 两次来刷新数据。

完整的代码集可以在这里找到:https://github.com/ttcg/react-redux-todo/tree/todocrud/src

【问题讨论】:

    标签: reactjs react-redux


    【解决方案1】:

    我设法通过以下方式解决了这个问题。

    主要问题是我试图以传统方式而不是 React-Redux 方式开发重定向。

    通常,我们会在单击按钮或执行某些操作后重定向到另一条路由,因为我们假设在操作执行完成之前它不会执行重定向。

    但是,Javascript 执行是异步的,它们不会等待上一行的完成。因此,它将始终重定向而无需等待上一个操作。网上很多教程都是用这种方式的。它可能适用于教程,因为没有延迟并且他们正在操作内存中的对象。

    按钮点击后重定向的错误方式

    submitNewTodo = event => {
        event.preventDefault();     
        this.props.addTodoItem(this.state.item);
    
        //redirect to Todo List Page after saving
        this.context.router.history.push(`/todo`); 
    }
    

    但在 React-Redux 中,数据流是单向的,我们需要在实现代码时考虑到该流。

    在 Reducer 中更改以返回标记 addTodoSuccess

    const todoReducer = (state = initialState, action) => {
        switch (action.type) {
            case actionTypes.ADD_TODO_ITEM_SUCCESS: {
                return { ...state, addTodoSuccess: true };
            }
            ...
            default:
                return state;
        }
    }
    

    映射 AddTodoPage 容器中的值以捕获标志

    const mapStateToProps = (state) => {
        let item = { id: uuidv4(), taskItem: '', doneBy: '' };
    
        return {
            item: item,
            addTodoSuccess: state.todo.addTodoSuccess
        };
    }
    

    在Render()方法中做重定向检查reducer返回的值

    {
    addTodoSuccess
    ? (<Redirect to={"/todo"} />)
    :
        <Container>
            <h4>Add New Todo</h4>
            ....
        </Container>
    }
    

    注意事项:

    1. 使用Promises可以解决,但是会破坏UniDirectional的Redux流程。

    2. 您不必为此类功能使用 Redux。但是,我正在学习 Redux 并尝试按照教程进行操作。

    3. 有些人可能会在 Actions/Reducers 中进行重定向。也有关于这种方式的争论。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-09
      • 1970-01-01
      相关资源
      最近更新 更多