删除编辑的输入并在当前输入中更新它
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
数据(它们的 value
和 done
值)的 单一真实来源 应该是父 App 组件。
为了解决这个问题,您需要在 <TaskListItem />
的渲染方法中使用道具 ({this.props.todo.value}
) 的值,而不是状态 ({this.state.currentValue}
)
这是一个fixed example version of your app
(我删除了导致错误的部分)
希望这对您有所帮助:)
抱歉,如果我的问题没有得到正确解释,我的反应很菜鸟,我需要你们的帮助,谢谢。 详细解释一下,我的编辑状态得到了完美更新,但问题是当我尝试删除它时,它正在删除最后添加的值。我知道我必须在点击删除按钮时更新状态,但我不知道如何……帮助不大。这是整个代码。请让我知道我哪里出错了,并给出解决方案。 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
数据(它们的 value
和 done
值)的 单一真实来源 应该是父 App 组件。
为了解决这个问题,您需要在 <TaskListItem />
的渲染方法中使用道具 ({this.props.todo.value}
) 的值,而不是状态 ({this.state.currentValue}
)
这是一个fixed example version of your app
(我删除了导致错误的部分)
希望这对您有所帮助:)