Article From:https://segmentfault.com/q/1010000013341829

Following the introduction of various tutorials online, react decided to make a todolist to deepen the understanding of react.
Because before learning Vue for a while, using Vue to do todolist directly brings the final effect map to react.

The above picture is made with Vue
Say what the todo has:
1.When the input box is entered, press enter or click on the new button to add the text to the list below.
2.The marking part of each previous checkbox is checked and cannot be edited.
3.Each mouse has a’x’click deleted on the right side, which can delete the item.
4.The input[type=’text’] used in the text part can modify the text by clicking on the text. When a defocus event or an event is pressed back, judge whether the text is consistent with the previous text, disagree with the pop-up confirmation box, confirm the box click confirmation to modify, and click Cancel to the previous text.Yes.

The problem is that when react is used, the attributes of input[type=’text’] must match onChange with value, but I will not do this one.
If one happens with defaultValue, it doesn’t matter if you don’t click the delete confirmation, but when you click to delete one item, defaultValue does not render again, so the text content that is displayed after the delete list is deleted or the content is deleted.
I would like to have a look at my code and help me.

I also hope that there will be suggestions for improving code optimization and so on.

Post the changed code:

import React, { Component } from 'react';

import './App.less';

//Remove the space between two sidesFunction trim (STR) {Return str.replace (/ (^\s*) \s*$(\s*$) /g, "");}/ / additional item componentsClass AddPanel exTends Component {Constructor (props) {Super (props);This.addhandler = this.addhandler.bind(this);/*this.ButtonAddHandler = this.ButtonAddHandler.bind (this); * /}Addhandler (E) {VAR ListDataArr = this.props.ListDataArr;Var inputStr = this.input.value;Var trimStr = trim(inputStr);If ((e.target.type = = ='text'& & e.keyCode = = = 13) = e.target.type = = ='buTton') {If (trimStr) {ListDataArr.push ({Text:trimStr,Ischecked: fAlse});This.props.SetInputToListData (ListDataArr);}This.inpUt.value = '';}}Render () {Return (< div className= "addpanel Clearfix" >< button type= "button" onClick={this.addhandler}> new < /button>< div classNAme= "addinput" >< input type= "text" placeholder= "Please add items" onKeyDown={this.addhandler}Ref={input => this.input=input} />< /div>< /div>)}}/ / display agentItem componentsClass ListPanel extends Component {Constructor (props) {Super (props);This.state = {{InputText: ''};This.changeChecked = this.changeChecked.bind (this);This.modificaTion = this.modification.bind (this);This.keydownModification = this.keydownModification.bind (th)Is);This.deletehandler = this.deletehandler.bind (this);This.textrecord = this.textrecord.bInd (this);This.bindinputvalue = this.bindinputvalue.bind (this);}ChangeChecked (index) {Var ListDataArr = this.props.ListDataArr;ListDataArr[index].ischecked =! ListDataArr[index].isChecked;This.props.checkhandler (ListDataArr);}Modification (index, e) {Var ListDataArr= this.props.ListDataArr;Var afterStr = trim (e.target.value);If (afterStr = = = this.state.in)PutText) {ListDataArr[index].text = afterStr;This.props.checkhandler (ListDataArr);}else{Var conf = window.confirm ('make sure to modify?');If (CONF) {ListDataArr[index].text =AfterStr;This.props.checkhandler (ListDataArr);}else{ListDataArr[index].text= this.state.inputText;This.props.checkhandler (ListDataArr);}}}KeydownMoDification (index, e) {If (e.keyCode = = = 13) {This.modification (index, e);}}DeletehAndler (index, e) {Var ListDataArr = this.props.ListDataArr;Var conf = window.confirm ('do you have to delete?");If (CONF) {ListDataArr.splice (index, 1);This.props.checkhandler (ListDataArr);}}Textrecord (index, e) {This.setState ({InputText: e.target.value})Console.log (e.target.value);}Bindinputvalue (index, e) {Var ListDataArr = this.props.ListDaTaArr;ListDataArr[index].text = e.target.value;This.props.checkhandler (ListDataArr);}Render () {Var ListDataArr = this.props.ListDataArr;Return (< div className= "listpAnel ">< h3> your to-do < /h3>< ul>{ListDataArr.map ((item, index) => {Return (< Li key={index+1}>< span>< input type= "checkbox" onChange={this.changeChecked.bind(null, index)} checked={item.ischecked? True:false}/>{index+1+ ":"}< /span>< div>< input type= "text" value={item.text} onChange={this.bindinputvalue.bind (null, index)} onFocus={this.textrecord.bind (null, index)} onBlur={this.modification.bind (this, index)} onKeyDown={this.keydownModification.bind (null, index)}Disabled={item.ischecked? True:false} className={item.ischecked?'done':''}/>&lT; /div>< I onClick={this.deletehandler.bind (null, index)}> < /i>< /li>)})}< /ul>< /div>);}}Class Statistics extends Component {Render () {Var ListDataArr = this.props.ListDataArr,Total = ListDataArr.length,Finished = 0,Nofinished = 0;ListDataArr.forEach (function (item, index) {If (item.ischecked) {Finished++;}else{Nofinished++;}})Return (< div classNaMe= "statisticsPanel" >Total: < span className= "color01" > {total}< /span> matters, completion.Item: < span className= "color02" > {finished}< /span> one, agent: < span className= "color03";{nofinished}< /span>< /div>);}}Class App extends Component {ConstrUctor (props) {Super (props);This.state = {{ListDataArr: storage.fetch (),}ThiS.SetInputToListData = this.SetInputToListData.bind (this);}SetInputToListData (ARR) {Arr.maP ((item, index) => {Return (item.id = index);});This.setState ({ListDataArr:Arr});Storage.save (ARR);}Render () {Console.log (JSON.stringify (this.state.ListD)AtaArr))Return (< div id= "app" >< AddPanel ListDataArr={this.state.ListDAtaArr} SetInputToListData={this.SetInputToListData}> < /AddPanel>< ListPanel ListDataArr={this.state.ListDataArr} checkhandler={this.SetInputToListData}> < /ListPanel>< Statistics ListDataArr={this.state.ListDataArr}> < /Statistics>< /div>);}}/ / create localstorageVar storageName ='todolist-react';Const storage = {{Fetch () {RetUrn JSON.parse (localStorage.getItem (storageName)]},Save (jsondata) {LocalStorage.sEtItem (storageName, JSON.stringify (jsondata));}}Export default App;

According to the solution to the first floor, change defaultValue to value and add onChange event.
Now it’s up to what I want.

Although the function is done, I think my code looks confused, some of the code feels redundant but does not know how to optimize it, such as the ListPanel component.

<input type="text" value={item.text} onChange={this.bindinputvalue.bind(null,index)} onFocus={this.textrecord.bind(null,index)} onBlur={this.modification.bind(this,index)} onKeyDown={this.keydownModification.bind(null,index)} disabled={item.ischecked?true:false} className={item.ischecked?'done':''}/>

In this section, I added a lot of events, whether this piece can remove unnecessary code, or whether the methods called by these events can be integrated to write, and then each event I want to pass the current object as a parameter, and I write that.Bind (null, index) is passing the object inIndex value of an array

Answer 0:

Since the use ofdefaultValue,Show that your component is an uncontrolled component and no legal person controls it.value。anddefaultValueIt can only be used once

The solution is to turn it into a controlled component, and as you say, it will not work.onChange,This can be searched. It’s not difficult

Similar Posts:

Leave a Reply

Your email address will not be published. Required fields are marked *