React Redux - 更新状态数组中的子项

时间:2017-07-22 03:41:07

标签: reactjs react-redux

所以我在Redux商店中有一个名为currentAccount的对象。它有一个名为groups的子数组,它有一个名为tasks的子数组。

现在,我可以通过或多或少的方式在Angular中轻松更新一个任务:

function updateTask(task){
   http.post('xyz/updateTask', function(updatedTask){
        task = updatedTask;
   });
}

......而且工作得很好。

在React中,我可以将数据发送到actions,使用Axios将其发布到API,但是......如何查找和更新旧任务?

我可以:

  • 让服务器再次返回整个currentAccount对象,然后将其转换为JSON字符串并返回(强制Redux重新渲染整个树),
  • ...或者在forEach中执行forEach以通过其ID找到任务,然后替换它(虽然我不确定Redux是否会接受更改)

但这两件事让我感到非常疯狂。有没有更简单的方法,或者只是React的工作原理?

,如果这是一个愚蠢的问题,请道歉,我真的不确定如何说出来,哈哈。

2 个答案:

答案 0 :(得分:0)

从http呼叫收到回复后,发送更新商店的操作。您需要访问组件中的调度,因此您可以使用mapDispatchToProps来提供功能。

以下是创作者ReduxDan Abramov提供的精彩入门教程。

此代码示例可以为您提供帮助。

// I'm using this stateless functional component to
// render the presentational view
const Task = ({ label, info }) => (
    <div className="task">
        <h3{ label }</h3>
        <p{ info }</p>
    </div>
);

// this is the class that receives props from connect
// and where we render our tasks from
class Tasks extends PureComponent {

    // once your component is mounted, get your
    // http data and then disptach update action
    componentDidMount() {
        // using axios here but you can use any http library
        axios.post( "/some_url", task )
            .then( ( response ) => {

                // get update provided by mapDispatchToProps
                // and use it to update tasks with response.data
                const { update } = this.props;
                update( response.data );
            })
            .catch( ( error ) ) => {
                // handle errors
            }
    }

    render() {
        // destructure tasks from props
        const { tasks } = this.props;

        // render tasks from tasks and pass along props
        // if there are no tasks in the store, return a loading indicator
        return (
            <div className="tasks">
                {
                    tasks ? tasks.map(( task ) => {
                        return <Task
                            label={ task.label }
                            info={ task.info }
                        />
                    }) :
                    <div className="loading">Loading...</div>
                }
            </div>
        );
    }
}

// this will provide the Tasks component with props.task
const mapStateToProps = ( state ) => {
    return {
        tasks: state.tasks
    }
}

// this will provide the Tasks component with props.update
const mapDispatchToProps = ( dispatch ) => {
    return {
        update: ( tasks ) => {
            dispatch({
                type: "UPDATE_TASKS",
                tasks
            });
        }
    }
}

// this connects Task to the store giving it props according to your
// mapStateToProps and mapDispatchToProps functions
export default Task = connect( mapStateToProps, mapDispatchToProps )( Task );

您需要一个处理"UPDATE_TASK"操作的reducer。 reducer更新商店,并且考虑到组件已连接,它将接收具有更新商店值的新道具,并且任务将在DOM中更新。

编辑:为了解决减速器问题,这是另一个例子。

import { combineReducers } from "redux";

const tasks = ( state = [], action ) => {
  switch( action.type ) {
    case "UPDATE_TASKS":
      // this will make state.tasks = action.tasks which
      // you dispatched from your .then method of the http call
      return action.tasks;
    default:
      return state;
  }
};

const other = ( state = {}, action ) => {
  ...
}

const combinedReducers = combineReducers({
  tasks,
  other
});

const store = createStore(
    combinedReducers/*,
    persisted state,
    enhancers*/
);    

/*

  The above setup will produce an initial state tree as follows:

  {
    tasks: [ ],
    other: { }
  }

  After your http call, when you dispatch the action with the tasks in
  the response, your state would look like

  {
    tasks: [ ...tasks you updated ],
    other: { }
  }

*/

答案 1 :(得分:0)

如果有其他人被卡住了,我想我已经把它整理出来了。

我只是传递任务父母的所有索引,然后使用&#39; dotPoints&#39;设置这样的状态:

dotProp.set(state, `currentProject.groups.${action.groupIndex}.tasks.${action.taskIndex}`, action.task);

到目前为止似乎是一个相当简洁的解决方案。