扩展数组上的意外结果拼接

时间:2019-05-26 01:28:08

标签: javascript arrays reactjs

此代码适用于内置react的简单待办事项应用程序。今天,我试图将我的选项1代码重构为类似选项2的内容,但惊讶地发现它破坏了我的removeTask功能。在故障排除期间,我还尝试了选项3,其结果相同。我正在努力找出原因;对我来说,选项2和3与选项1看起来几乎一样,只是比较干净。实施选项2或3时,我没有收到任何错误,但是单击removeTask现在会删除所有先前的任务。这三个之间有什么区别?


问题代码:

//Option 1 (working)
removeTask = (event, index) => { 
  event.stopPropagation();
  const removedTaskArray = [...this.state.tasksarray];

  removedTaskArray.splice(index, 1);                                      
  this.setState({ tasksarray: removedTaskArray });         
};


//Option 2 (broken)
removeTask = (event, index) => {                          
  event.stopPropagation();                                 
  const removedTaskArray = [...this.state.tasksarray].splice(index, 1);     

  this.setState({ tasksarray: removedTaskArray });    
};


//Option 3 (broken)
removeTask = (event, index) => {                          
  event.stopPropagation();                                 
  const copyOfTasksArray = [...this.state.tasksarray]    
  const removedTaskArray = copyOfTasksArray.splice(index, 1);     

  this.setState({ tasksarray: removedTaskArray });    
};




完整(有效)代码:

import React, { Component } from 'react';
import './App.css';

/* InputTaskForm renders a form, and returns the input to our storeTask method. */
const InputTaskForm = ({ formValidation }) => { 
    return (                                      
      <form name="charlie" onSubmit={formValidation}>
        <input name="userinput" type="text" placeholder="Task..." /> 
        <button type="submit">Submit</button>
      </form>
    );
}

const DisplayTasks = ({ tasks, removeTask, strikeTask }) => {
  return (
    <div id="orderedList">
      <ol>
        {tasks.map((task, index) => (
          <li onClick={() => strikeTask(index)} key={index} >
            {task.strike ? <strike>{task.title}</strike> : task.title}
            <button id="removeButton" onClick={event => removeTask(event, index)} >Remove</button>
          </li>
        ))}
      </ol>
    </div>
  );
};

class App extends Component {
  state = {
    userinput: '',
    tasksarray: [],                               
  }


/* ============================================== #FUNCTIONS ============================================== 
=========================================================================================================== */
formValidation = event => {                                 // event prop passed from InputTaskForm component
  event.preventDefault();                                   // prevent form from auto-refreshing on submit
  const userInput = event.target.userinput.value            // userInput stored
  const userInputIsBlank = userInput.trim().length < 1      // trim (remove) prefixed and affixed spaces, then check length

  userInputIsBlank 
    ? alert(`Error: invalid submission`) 
    : this.storeTask(userInput);
};


storeTask = userInput => {                                  // userInput passed from formValidation function
    this.setState({
      userinput: userInput,
      tasksarray: [...this.state.tasksarray, { title: userInput, strike: false } ] //create a copy of tasks array then add a new object into the array filled out with user input
    });
    document.forms["charlie"].reset();
};


//Option 1 (working)
removeTask = (event, index) => { 
  event.stopPropagation();
  const removedTaskArray = [...this.state.tasksarray];

  removedTaskArray.splice(index, 1);                                      
  this.setState({ tasksarray: removedTaskArray });         
};


strikeTask = index => {                                    // index prop passed from DisplayTasks component
  const { tasksarray } = this.state
  const selected = tasksarray[index];

  this.setState({                                           
    tasksarray: [                                           // change tasksarray state to: [prior slice, change, after slice]
      ...tasksarray.slice(0, index),                        // slice off (copies) of array elements prior to index element
      Object.assign(selected, {strike: !selected.strike}),  // invert the selected line's strike value
      ...tasksarray.slice(index + 1)                        // slice off (copies) of array elements after index element
    ]
  });
};


componentDidUpdate() {
  console.log(this.state.tasksarray);                       // debugging :) 
};


/* =============================================== #RENDER ================================================ 
=========================================================================================================== */
  render() { 
    const { tasksarray } = this.state
    const { formValidation, storeTask, removeTask, strikeTask } = this

    return (
      <div>
        <InputTaskForm 
          task={storeTask}
          formValidation={formValidation} />


        <DisplayTasks 
          tasks={tasksarray} 
          removeTask={removeTask} 
          strikeTask={strikeTask} />
      </div>
      );
    };
};


/* ================================================ #EXPORT =============================================== 
=========================================================================================================== */
export default App;

2 个答案:

答案 0 :(得分:1)

一切都归结为了解Array##splice的作用,实际上它返回一个包含已删除项目的数组。这是一个小例子:

const a = [1, 2, 3, 4, 5].splice(3, 1); // same as a = [4]
const b = [1, 2, 3, 4, 5];
const c = b.splice(3, 1); // same as b = [1, 2, 3, 5] and c = [4]

答案 1 :(得分:1)

Return value的接合点是

  

包含删除的元素的数组。如果只有一个元素是   移除后,将返回一个元素的数组。如果没有元素   删除后,将返回一个空数组。

因此,在您的2 nd 和3 rd 方法中,您将放置已删除的元素数组

因此您只需将代码更改为

removeTask = (event, index) => {                          
  event.stopPropagation();                                 
  const removedTaskArray = [...this.state.tasksarray]
  removedTaskArray.splice(index, 1);     
  this.setState({ tasksarray: removedTaskArray });    
};