在将对象从数组移动到数组到React中的另一个对象时镜像位置

时间:2019-06-13 09:04:19

标签: javascript arrays reactjs ecmascript-6 javascript-objects

当我调用createTodo函数时,this.state.todos被添加到新的待办事项中。具有time属性的对象想要移动到对象times中的select数组,但是times被加倍。 我认为应该归咎于.slice方法并复制数组。如何解决呢?

Todo

class Todo extends Component {

  render() {
    return (
       <li>
        <div>
          {this.props.todo.description}
        </div>
      </li>
    )
  }
}

应用

class App extends React.Component {
  constructor() {
    super();

    this.state = {

      todos: [
        {
          time: '00:00:10',
          description: 'Hello'
        },
        {
          time: '00:00:20',
          description: 'World'
        }
       ],
      todo: {
        'time': '00:00:30',
        'description': 'W'
      },
      select: {
        "times": [{ 'time': '00:00:40' }, { 'time': '00:00:50' }],
        "description": " ytytyty",
        "id": 3,
        "title": "gfgfgfgfgf"
      }
     };
  }



  addTodo = (todo) => {
    const news = this.state.todos.slice();
    news.push(this.state.todo);
    this.setState({ todos: news });
  };


  render() {

    this.state.todos.forEach(t => {
      if (t.time) this.state.select.times.push({
        time: t.time
      })
    });

    console.log(this.state.todos);
    console.log(this.state.select);

    return (
      <div>
        <ul>
          {
            this.state.todos
              .map((todo, index) =>
                <Todo
                  key={index}
                  index={index}
                  todo={todo}
                />
              )
          }
        </ul>
        <button onClick={this.createTodo}>button</button>
      </div>
    );
  }

console.log(this.state.select) -> return-->

times: [
 {time: "00:00:40"}
 {time: "00:00:50"}
 {time: "00:00:10"} //repeat
 {time: "00:00:20"} //repeat
 {time: "00:00:10"}
 {time: "00:00:20"}
 {time: "00:00:30"}
 title: "gfgfgfgfgf"
]

期待效果

times: [
     {time: "00:00:40"}
     {time: "00:00:50"}
     {time: "00:00:10"}
     {time: "00:00:20"}
     {time: "00:00:30"}
     title: "gfgfgfgfgf"
    ]

演示 https://stackblitz.com/edit/react-jfkwnu

加载组件后,它应为:selectTodo: {"times": [{'time': '00: 00: 40 '}, {' time ':' 00: 00: 50 '}], "description": "ytytyty", "id": 3, "title": "gfgfgfgfgf"}

首次点击按钮:-> selectTodo: {times: [{time: "00:00:40"} {time: "00:00:50"} {time: "00:00:10"} {time: " 00:00:20 "} {time:" 00:00:30 "} title:" gfgfgfgfgf "]," description ":" ytytyty "," id ": 3," title ":" gfgfgfgfgf "}

第二次点击按钮更改-> selectTodo: {times: [{time: "00:00:40"} {time: "00:00:50"} {time: "00:00:10"} {time: "00 : 00: 20 "} {'time': '00: 00: 30'}, {time:" 00:00:30 "} title:" gfgfgfgfgf "]" description ":" ytytyty "," id ": 3 , "title": "gfgfgfgfgf"}

1 个答案:

答案 0 :(得分:2)

据我了解,您想独立维护todosselectTodo,但始终将所有todos次镜像到selectTodo.times

总结:

  1. 组件状态在构造函数中设置
  2. 组件安装
  3. 用户创建待办事项时
    1. 如果这是第一次,现有的todos将镜像到selectTodo.times
    2. 将新的待办事项推送到todosselectTodo.times

要知道用户是否已经使用过createTodo方法,我刚刚将withInitialTodos添加到了该状态。它不是很干净,但是可以满足您的需要。

请注意,正如Bergi在上面的评论中所述,您应该避免在render方法中更新状态。

constructor() {
    super();

    this.state = {
        withInitialTodos: true,
        todos: [
            {
                time: '00:00:10',
                description: 'Hello'
            },
            {
                time: '00:00:20',
                description: 'World'
            }
        ],
        todo: {
            'time': '00:00:30',
            'description': 'W'
        },
        selectTodo: {
            "times": [{ 'time': '00:00:40' }, { 'time': '00:00:50' }],
            "description": " ytytyty",
            "id": 3,
            "title": "gfgfgfgfgf"
        }
    };
}

createTodo = (todo) => {
    this.setState({
        withInitialTodos: false,
        todos: [].concat(this.state.todos, this.state.todo),
        selectTodo: {
            ...this.state.selectTodo,
            times: [].concat(
                this.state.selectTodo.times,
                this.state.withInitialTodos ? this.state.todos.map(({ time }) => ({ time })): [],
                {
                  time: this.state.todo.time
                }
            )
        }
    });
}

render() {

    console.log(this.state.todos);
    console.log(this.state.selectTodo.times);

    return (
        <div>
            <ul>
                {this.state.todos.map((todo, index) => (
                    <Todo
                      key={index}
                      index={index}
                      todo={todo}
                    />
                )}
            </ul>
            <button onClick={this.createTodo}></button>
        </div>
    );
}