删除编辑的输入并在当前输入中更新它

To delete the edited input and update the it in the current input

抱歉,如果我的问题没有得到正确解释,我的反应很菜鸟,我需要你们的帮助,谢谢。 详细解释一下,我的编辑状态得到了完美更新,但问题是当我尝试删除它时,它正在删除最后添加的值。我知道我必须在点击删除按钮时更新状态,但我不知道如何……帮助不大。这是整个代码。请让我知道我哪里出错了,并给出解决方案。 app.js

import React, { Component } from 'react';
import Input from './input_bar';
import TaskList from './tasklist';

export default class App extends Component {

    constructor(props){
        super(props);
        this.state={
            inputValue:"",
            todos: [
                {value: 'Clean the room', done: false},
                {value: 'Wake up early', done:true}
            ],
            check:true,
            isHidden: true
        }
        this.onInputChange=this.onInputChange.bind(this);
        this.onSubmit=this.onSubmit.bind(this);
        this.onCheckClick=this.onCheckClick.bind(this);
        this.onDeleteClick=this.onDeleteClick.bind(this);
        this.onClearCompleted=this.onClearCompleted.bind(this);
        this.onCheckUncheckAll=this.onCheckUncheckAll.bind(this);
        this.noOfItems=this.noOfItems.bind(this);
    }

    onInputChange(event){
        this.setState({inputValue: event.target.value});
    }

    onSubmit(event){
        event.preventDefault();
        const newTodo ={
            value:this.state.inputValue,
            done:false
        };
        const todos = this.state.todos;
        todos.push(newTodo);
        this.setState({todos, inputValue:''})
    }

    onCheckClick(index){
        const todos= this.state.todos;
        todos[index].done= !todos[index].done;
        this.noOfItems();
        this.setState({todos})
    }

    onDeleteClick(index){
        const todos=this.state.todos;
        todos.splice(index,1);
        this.setState({todos});
    }

    onClearCompleted(){
        const todos=this.state.todos;

        for( let i = 0 ; i < todos.length; i++){
            if ( todos[i].done === true) {
                todos.splice(i, 1);
                i=i-1;
            }
        }
        this.setState({todos});
    }

    onCheckUncheckAll(){
        const todos= this.state.todos;
        for( let i = 0 ; i < todos.length; i++){
            todos[i].done= this.state.check;
            this.setState({check: !this.state.check});
        }
        this.setState({todos});
    }

    noOfItems(){
        const todos=this.state.todos;
        let itemsLeft = todos.length;
        for( let i = 0 ; i < todos.length; i++) {
            if (todos[i].done === true) {
                itemsLeft = itemsLeft - 1;
            }
        }
        return(itemsLeft);
    }

    render() {
     return (
       <div>

          <Input
              onInputChange={this.onInputChange}
              inputValue={this.state.inputValue}
              onSubmit={this.onSubmit}
              onCheckUncheckAll={this.onCheckUncheckAll}
          />

          <TaskList
              onCheckClick={this.onCheckClick}
              onDeleteClick={this.onDeleteClick}
              onClearCompleted={this.onClearCompleted}
              noOfItems={this.noOfItems}
              todos={this.state.todos}
          />

       </div>
     );
    }
}

input_bar.js

import React from 'react';

export default class Input extends React.Component{


    render(){
        return(
            <div className="Form">
                <button onClick={this.props.onCheckUncheckAll} className="CheckUncheck">
                    <i className="fa fa-angle-down"/>
                </button>
                <form onSubmit={this.props.onSubmit}>
                    <input
                        value={this.props.inputValue}
                        onChange={this.props.onInputChange}
                        className="toggle-all"
                        placeholder="What needs to be done?"
                    />
                </form>
            </div>
        );
    }
}

tasklist.js

import React from 'react';
import TaskListItem from './tasklistitems';

export default class TaskList extends React.Component{

    render(){
        return(
            <div className="List">
                {this.props.todos.map((todo, index) => {
                    return(
                        <TaskListItem
                            key={index}
                            index={index}
                            todo={todo}
                            onCheckClick={this.props.onCheckClick}
                            onDeleteClick={this.props.onDeleteClick}
                            noOfItems={this.props.noOfItems}
                        />
                    );
                })}
                <span>  {this.props.noOfItems()} items left </span>
                <a onClick={this.props.onClearCompleted} className="clearCompleted">Clear Completed</a>
            </div>
        );
    }
}

tasklistitems.js

import React from 'react';
import Ionicon from 'react-ionicons'

export default class TaskListItem extends React.Component{
    constructor(props){
        super(props);
        this.state={
            edit: false,
            currentValue: this.props.todo.value
        }

    }

    tick(){
        return(
                <Ionicon icon="ios-radio-button-off" fontSize="25px" color="#EDEDED"/>
        )
    }

    untick(){
        return(
                <Ionicon icon="ios-checkmark-circle-outline" fontSize="25px" color="#57C1AF"/>
        )
    }

    onEdit(event){
        this.setState({edit: true, currentValue: this.state.currentValue});
    }

    onEditDone(event){
        if(event.keyCode===13){
            //console.log(this.state.currentValue);
            this.setState({edit:false});
            this.props.todo.value= this.state.currentValue;
        }
    }

    onEditChange(event) {
        let _currentValue = event.target.value;
        //console.log("currentvalue",this.state.currentValue);
        this.setState({currentValue: _currentValue});
    }

    // onDeleteChange(){
    //
    //     // ----------------- What should I put here ---------------//
    //
    //
    // }

    render(){
        //console.log(this.state.currentValue);
        const viewStyle={};
        const editStyle={};

        if(this.state.edit){
            viewStyle.display= 'none';
        }else{
            editStyle.display='none';
        }

        return(
            <div>
                <div style={viewStyle}>
                    <div className="Task row" >
                        <div className="col-md-2">
                            <button onClick={()=>this.props.onCheckClick(this.props.index)}>
                                {this.props.todo.done ? this.untick():this.tick() }
                            </button>
                        </div>
                        <span >
                            <div className="col-md-9" onDoubleClick={this.onEdit.bind(this)}>
                                <span style={{color:this.props.todo.done ?'#e6e6e6' : '#4d4d4d',
                                    textDecoration: this.props.todo.done ? '#e6e6e6 line-through' : 'none',
                                    transition: 'text-decoration 0.5s, color 0.5s'
                                }}
                                >
                                    {this.state.currentValue}
                                </span>
                            </div>
                        </span>
                        <div className="col-md-1">
                            <button onClick={()=>this.props.onDeleteClick(this.props.index)} onMouseDown={onDeleteChange.bind(this)} className="destroy">
                                x
                            </button>
                        </div>
                    </div>
                </div>

                <input type="text"
                       onChange={this.onEditChange.bind(this)}
                       onKeyDown={this.onEditDone.bind(this)}
                       style={editStyle}
                       value={this.state.currentValue}/>
            </div>
        );
    }
}

tl;博士:
您不需要在 <TaskListItem/> 的状态下管理 currentValue。您应该使用 this.props.todo.value 来渲染它。这是 fix

详细:
此错误是由于以下事实引起的:在 <TaskListItem /> 组件上,您正在使用 todo.value 道具以便在组件的构造函数 (currentValue: this.props.todo.value) 上设置项目的当前值并使用此state 属性以呈现此值 ({this.state.currentValue})。

因为当这个值改变时(例如 - 当一个项目被删除时)这个值被父组件作为 prop 动态传递 - 它导致当新值通过 props 传递给组件时该值不改变因为它是从其内部状态获取的(不会在每次道具值更改时更新)。

换句话说。您需要将此值的真实来源从状态更改为道具。 todos 数据(它们的 valuedone 值)的 单一真实来源 应该是父 App 组件。

为了解决这个问题,您需要在 <TaskListItem /> 的渲染方法中使用道具 ({this.props.todo.value}) 的值,而不是状态 ({this.state.currentValue} )

这是一个fixed example version of your app

(我删除了导致错误的部分)

希望这对您有所帮助:)