首页 > 解决方案 > 在数组(状态)中添加的待办事项对象不会立即反转

问题描述

我正在前端使用 React-redux 创建 Todo CRUD 应用程序。当我将一个新的 todo 对象添加到 todos 列表(状态中的数组)时,我希望将新的 todo 呈现在最顶部,而不是最后一个。我只是将组件连接到 redux 状态(待办事项列表)并反转它。它起作用了,虽然不是立即,而是在一段时间后。我想问题出在生命周期中。索引组件连接到 redux 状态。渲染生命周期创建标记,映射到状态数组,然后 Componentdidmount 触发从而更新状态,然后重新渲染发生,因此视图。这不是立即发生,而是在几毫秒后发生。但我不确定也很困惑,因为我尝试了另一种生命周期方法,但没有结果......

todos 组件列表

Index.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { todoList } from '../actions/todoActions';
import TableRow from './TableRow';

class Index extends Component {

    componentDidMount() {
        this.props.todoList();
    };

    tabRow() {
        return this.props.allTodos.map(user => {
            return <TableRow obj={user} key={user._id} />
        });
    }

    render() {
      return (
        <div>
          <h3 align="center">Todo List</h3>
          <table className="table table-striped" style={{ marginTop: 20 }}>
            <thead>
              <tr>
                <th>Name</th>
                <th>Surname</th>
                <th>Task</th>
                <th colSpan="2">Action</th>
              </tr>
            </thead>
            <tbody>
              { this.tabRow() }
            </tbody>
          </table>
        </div>
      )
    }
};

const mapStateToProps = state => ({
    allTodos: state.todo.todos.reverse()
});

export default connect(
    mapStateToProps,
    { todoList }
)(Index);

创建待办事项

import React from 'react';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { registerTodo } from '../actions/todoActions';

class Create extends React.Component {
    constructor(props) {
        super(props);
        this.userChangeHandler = this.userChangeHandler.bind(this);
        this.onSubmit = this.onSubmit.bind(this);

        this.state = {
            name: '',
            surname: '',
            task: ''
        };
    }

    userChangeHandler(e) {
        this.setState({
            [e.target.name] : e.target.value
        });
    };

    onSubmit(e) {
        e.preventDefault();
        const newUserTodo = {
            name: this.state.name,
            surname: this.state.surname,
            task: this.state.task
        };
        this.props.registerTodo(newUserTodo, this.props.history);
    };

    render() {
        return(
            <div style={{marginTop: 10}}>
                <h3>Add New Task</h3>
                <form onSubmit={this.onSubmit}>
                    <div className="form-group">
                        <label>Add Name: </label>
                        <input 
                            type="text" 
                            name="name" 
                            className="form-control"
                            onChange={this.userChangeHandler}
                        />
                    </div>
                    <div className="form-group">
                        <label>Add Surname: </label>
                        <input 
                            type="text" 
                            name="surname" 
                            className="form-control"
                            onChange={this.userChangeHandler}
                        />
                    </div>
                    <div className="form-group">
                        <label>Add Todo Task: </label>
                        <input 
                            type="text" 
                            name="task" 
                            className="form-control"
                            onChange={this.userChangeHandler}
                        />
                    </div>
                    <div className="form-group">
                        <input type="submit" value="Create Todo" className="btn btn-primary"/>
                    </div>
                </form>
            </div>
        )
    }
};


export default connect(
  null,
  { registerTodo }
)(withRouter(Create));

待办事项

TableRow

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { deleteTodo } from '../actions/todoActions';

class TableRow extends Component {

  render() {
    return (
        <tr>
          <td>
            {this.props.obj.name}
          </td>
          <td>
            {this.props.obj.surname}
          </td>
          <td>
            {this.props.obj.task}
          </td>
          <td>
            <Link to={'/edit/'+this.props.obj._id} className="btn btn-primary">Edit</Link>
          </td>
          <td>
            <button onClick={this.props.deleteTodo.bind(this, this.props.obj._id)} className="btn btn-danger">Delete</button>
          </td>
        </tr>
    );
  }
};

const mapStateToProps = state => ({
  allTodos: state.todo.todos
});

export default connect(
  mapStateToProps,
  { deleteTodo }
)(TableRow);

行动

export const registerTodo = (userTodo, history) => dispatch => {
    axios
        .post('/api/users/add', userTodo)
        .then(res => {
            dispatch(setTodo(userTodo));
            history.push('/index');
        })
        .catch(err => console.log(err));
};

export const setTodo = todo => {
    return {
        type: ADD_TODO,
        payload: todo
    };
};

export const todoList = () => dispatch => {
    axios
        .get('/api/users')
        .then(res => {
            dispatch(getTodos(res.data));
        });
};

export const getTodos = todos => {
    return {
        type: GET_TODOS,
        payload: todos
    }
};

减速机

const initialState = {
    todos: []
};

export default function(state = initialState, action) {
    switch(action.type) {
        case ADD_TODO:
            return {
                ...state,
                todos: [...state.todos, action.payload]
            };
        case GET_TODOS:
            return {
                ...state,
                todos: [...action.payload]
            };
        default:
            return state;
    }
}

标签: reactjsredux

解决方案


老实说,我没有正确理解这个问题。但从我收集的信息来看,您希望新的待办事项放在其他待办事项的前面。这可以通过切换 ADD_TODO 减速器中的位置来完成。

case ADD_TODO:
    return {
        ...state,
        todos: [action.payload, ...state.todos]
    };

编辑:获取 todos 的 api 调用可能不一样,只是将其附加到末尾。在这种情况下,如果可以的话,你应该在那里处理它。(或)您应该在从 api 获取数据后自行执行此操作。由于这是在 componentDidMount() 中完成的,因此在第一次渲染后调用它会有延迟。添加微调器是一种解决方法。


推荐阅读