ReactJS:道具还是州?

时间:2017-05-24 06:05:45

标签: javascript reactjs

我正在使用react js编写一个简单的待办事项列表。应用程序将一些操作组合到操作列表中。 类的结构看起来像这样:

  

应用

     

--- GroupOfActions

     

------ ListOfActionsRow

     

------ ActionRow

全局var动作中的所有数据存储看起来像(它是一个全局var):

  

var actions = [{list:' some list',color:'#79fa5f',name:' some   行动',优先:' 0',完成:真}}

当用户更改操作名称或列表名称时,应在"操作"中更改。在DOM中。我可以在" action"中更改它,但在DOM中更改它的最佳模式是什么? 现在我正在使用道具。这是我的代码的一部分:



class App extends React.Component {
    constructor(props){
		super(props);
		actions=[];
    //parsing actions from localStorage
	}	
	
	render() {
		return(
	      <GroupOfActions actions={actions} />
	    );
	}
}

class GroupOfActions extends React.Component {	 
	render (){
		var rows=[];
		var lastList=null;
		this.props.actions.forEach(function(action){
			if (action.list!==lastList){
				rows.push(<ListOfActionsRow list={action.list} key={action.list} color={action.color} />);
			}
			rows.push(<ActionRow action={action} color={action.color} list={action.list}  key={action.name} />);
			
			lastList=action.list;
		});
		
		return(
		<div className="container" >
		{rows}			
		</div>
		);
	}
}

class ActionRow extends React.Component {

onNameChange(){
		var targetAction=JSON.parse(JSON.stringify('{\"list\":\"'+
		                this.props.list+
						'\",\"color\":\"'+
						this.props.color+
						'\",\"name\":\"'+
						this.props.action.name+
						'\",\"priority\":\"'+
						this.props.action.priority+
						'\",\"done\":'+
						this.props.action.done+
						'}'));
		console.log(targetAction);
		console.log(JSON.stringify(actions));
		var toDoList=JSON.stringify(actions);
		var startIndex=toDoList.indexOf(targetAction);
		var endIndex=startIndex+targetAction.length;
		if (startIndex>-1){
			var nameStartIndex=targetAction.indexOf('\",\"name\":\"');
			var nameEndIndex=targetAction.indexOf('\",\"priority\":\"');
			toDoList=toDoList.substring(0,startIndex)
			        +toDoList.substring(startIndex,(nameStartIndex+11))
					+this.refs.newName.value
					+toDoList.substring(nameEndIndex+1);
			console.log(toDoList);
			localStorage.setItem('toDoList',toDoList);
			actions=JSON.parse(localStorage.getItem('toDoList'));
			console.log(actions);
			this.props.action.name=this.refs.newName.value;
		} else {console.log(startIndex);}
	}



	render () {
		return (
		<div>
		   <div className={'row '+(this.state.edition?'hidden':'')} >
		      <div className="col-md-3" ref='oldName' onClick={this.editActionRow}>{this.props.action.name}</div>
              <div className="col-md-1" onClick={this.editActionRow} style={{width:'20%'}}>{this.props.action.priority}</div>
			  <div className="col-md-1" onClick={this.editActionRow}><input type='checkbox' ref='oldDone' checked={this.props.action.done} /></div>
		   </div>
	       <div className={'row '+(this.state.edition?'':'hidden')}>
		   <div className="col-md-6" onClick={this.editActionRow} style={{backgroundColor:'#fafafa'}}>
		        <input type='text' ref='newName' defaultValue={this.props.action.name} onChange={this.onNameChange} />
			            <label>Priority</label>
			            <select defaultValue={this.props.action.priority} onChange={this.onPriorityChange} ref='newPriority'>
			                <option value="0">0</option>
				            <option value="1">1</option>
				            <option value="2">2</option>
			            </select>
			            <label>Done</label>
			            <input type='checkbox' defaultChecked={this.props.action.done} ref='newDone' onChange={this.onDoneChange} />
		    </div>
			</div>
		</div>
		)
	}
}

class ListOfActionsRow extends React.Component {
	onNameOfListChange() {
		var oldNameOfList=this.props.list;
		var newNameOfList=this.refs.newNameOfList.value;
		var toDoList=JSON.stringify(actions);
		var newToDoList;
		for (var i=0;i<toDoList.length;i++) {
			var nameIndex=toDoList.indexOf(oldNameOfList,i);
			if (nameIndex==-1) continue;
			i=nameIndex;
			var nameEndIndex=nameIndex+oldNameOfList.length;
			newToDoList=toDoList.substring(0,nameIndex)
			        +newNameOfList
			        +toDoList.substring(nameEndIndex);
		} 
			
		console.log(newToDoList);
		localStorage.setItem('toDoList',newToDoList);
		actions=JSON.parse(localStorage.getItem('toDoList'));
		console.log(actions);
		this.props.list=this.refs.newNameOfList.value;
		
	}
	
	render() {
		return (
		<div>
		   <div className={'row '+(this.state.editionOfList?'hidden':'')} >
		      <div className="col-md-6" onClick={this.editListRow} >
		         <div className="well well-small lead" style={{backgroundColor:'{this.props.color}'}} style={{marginTop:'20px'}} ref='oldNameOfList'>
		            {this.props.list}
		         </div>
		      </div>
		   </div>
		   <div className={'row '+(this.state.editionOfList?'':'hidden')} >
		   <div className="col-md-6" >
		      <div className="well well-small lead" onClick={this.editListRow} style={{backgroundColor:'#fafafa'}}>
			     <input type='text' ref='newNameOfList' defaultValue={this.props.list} onChange={this.onNameOfListChange} />
			            <label>Color</label>
			            <select>
			                <option value="0">Yellow</option>
				            <option value="1">Blue</option>
				            <option value="2">Green</option>
			            </select>
			  </div>
		    </div>
		   </div>
		   <div className="row" style={{marginBottom:'20px'}}>
		       <div className="col-md-2">
		   </div>
		</div>
		);
	}
}
&#13;
&#13;
&#13;

在ActionRow行中

&#13;
&#13;
this.props.action.name=this.refs.newName.value;
&#13;
&#13;
&#13;

工作正确。在ListOfActionRow中,类似的行会出错:

&#13;
&#13;
this.props.list=this.refs.newNameOfList.value;
&#13;
&#13;
&#13;

在这种情况下可能会使用道具是反模式的吗?为什么同一个命令在一个案例中起作用但在另一个案例中不起作用?

1 个答案:

答案 0 :(得分:1)

它不是改变像this.props.action.name=this.refs.newName.value;这样的道具的正确方法,理想的方法是将一个函数从父组件传递给子组件,并从子组件调用它在父组件中设置一个值然后传递给孩子

同样,React DOCS建议对callback使用refs方法而不是字符串方法

例如,在App组件中创建一个更改列表名称的函数

class App extends React.Component {
    constructor(props){
        super(props);
        actions=[];
    //parsing actions from localStorage
    }   
    changeListName = (val) => {
            /// take action here
    }
    render() {
        return(
          <GroupOfActions actions={actions} changeListName = {(val) => {this.changeListName}}/>
        );
    }
}


class GroupOfActions extends React.Component {   
    render (){
        var rows=[];
        var lastList=null;
        this.props.actions.forEach((action) =>{
            if (action.list!==lastList){
                rows.push(<ListOfActionsRow list={action.list} key={action.list} color={action.color} changeListName={(val) => this.props.changeListName(val)}/>);
            }
            rows.push(<ActionRow action={action} color={action.color} list={action.list}  key={action.name} />);

            lastList=action.list;
        });

        return(
        <div className="container" >
        {rows}          
        </div>
        );
    }
}

class ListOfActionsRow extends React.Component {
    onNameOfListChange() {
        var oldNameOfList=this.props.list;
        var newNameOfList=this.refs.newNameOfList.value;
        var toDoList=JSON.stringify(actions);
        var newToDoList;
        for (var i=0;i<toDoList.length;i++) {
            var nameIndex=toDoList.indexOf(oldNameOfList,i);
            if (nameIndex==-1) continue;
            i=nameIndex;
            var nameEndIndex=nameIndex+oldNameOfList.length;
            newToDoList=toDoList.substring(0,nameIndex)
                    +newNameOfList
                    +toDoList.substring(nameEndIndex);
        } 

        console.log(newToDoList);
        localStorage.setItem('toDoList',newToDoList);
        actions=JSON.parse(localStorage.getItem('toDoList'));
        console.log(actions);
        this.props.changeListName(this.newNameOfList.value);

    }

    render() {
        return (
        <div>
           <div className={'row '+(this.state.editionOfList?'hidden':'')} >
              <div className="col-md-6" onClick={this.editListRow} >
                 <div className="well well-small lead" style={{backgroundColor:'{this.props.color}'}} style={{marginTop:'20px'}} ref={(list) => {this.oldNameOfList}}>
                    {this.props.list}
                 </div>
              </div>
           </div>
           <div className={'row '+(this.state.editionOfList?'':'hidden')} >
           <div className="col-md-6" >
              <div className="well well-small lead" onClick={this.editListRow} style={{backgroundColor:'#fafafa'}}>
                 <input type='text' ref={(list) => {this.newNameOfList}} defaultValue={this.props.list} onChange={this.onNameOfListChange} />
                        <label>Color</label>
                        <select>
                            <option value="0">Yellow</option>
                            <option value="1">Blue</option>
                            <option value="2">Green</option>
                        </select>
              </div>
            </div>
           </div>
           <div className="row" style={{marginBottom:'20px'}}>
               <div className="col-md-2">
           </div>
        </div>
        );
    }
}