defaultValue在React中提取最后一个值

时间:2017-12-01 00:35:15

标签: javascript reactjs

如果我点击一个特定的ToDos编辑按钮,它的值应该在textarea内默认,但每次最后一个ToDo默认,有人可以帮忙,无论是使用ref是正确的选择还是其他什么,那么我错了什么我想做什么?

 handleEdit() {
  e.preventDefault();
  .....

}  

renderDisplay() {
    return(
      <div>
       {
        this.props.listArr.map((list,i) => {
           return(
             <div key={i} index={i} ref="newText">
              <li>{list}
                <div>
                 <button className="btn btn-primary btn-xs glyphicon glyphicon-pencil"
                         onClick={this.handleEdit.bind(this)}
                 />
                </div>
              <hr/>
              </li>
             </div>
           )})
       }
       </div>
    );
  }


  renderForm() {
   return(
      <div>
        <textarea className="form-control" defaultValue={this.refs.newText.innerText} rows="1" cols="100" style={{width: 500}}/>
      </div>
    )
  }

  render() {
      if(this.state.editing) {
        return this.renderForm();
      }else {
        return this.renderDisplay();
      }
    }
}

1 个答案:

答案 0 :(得分:1)

首先,您使用old ref API。您应该使用this one,其中使用带有回调的this将ref设置为类的实例。

<input ref={ref => {this.myInput = ref}} />

然后您只需引用this.myInput即可访问其值。

至于你的“bug”,请记住你正在循环并覆盖ref。所以最后的引用赋值将是数组中的最后一项。

 this.props.listArr.map((list,i) => {
           return(
             <div key={i} index={i} ref="newText">
              <li>{list}

总会有1 newText参考,它始终是数组中的最后一项。

您应该根据项id呈现不同的引用名称,然后将项目的id传递给renderForm,以便它可以访问相关的引用。

话虽如此,我真的建议将todo提取到不同的组件以及表单。在这种情况下,我没有看到使用ref的正当理由。

修改
作为评论的后续内容,这里有一个小例子,说明如何使用组件代替refs,以便从子级获取信息,如值等。

class Todo extends React.Component {
  onClick = () => {
    const { todoId, onClick } = this.props;
    onClick(todoId);
  }

  render() {
    const { value, complete } = this.props;
    return (
      <div
        style={{ textDecoration: complete && 'line-through' }}
        onClick={this.onClick}
      >
        {value}
      </div>
    );
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      todos: [
        { id: '1', value: 'to do this', complete: false },
        { id: '2', value: 'todo that', complete: true },
        { id: '3', value: 'will do it later', complete: false }]
    }
  }

  toggleTodo = (todoId) => {
    const { todos } = this.state;
    const nextState = todos.map(todo => {
      if (todo.id !== todoId) return todo;
      return {
        ...todo,
        complete: !todo.complete
      }
    });
    this.setState({ todos: nextState });
  }

  render() {
    const { todos } = this.state;
    return (
      <div >
        {
          todos.map((todo) => {
            return (
              <Todo
                complete={todo.complete}
                key={todo.id}
                todoId={todo.id}
                value={todo.value}
                onClick={this.toggleTodo}
              />
            )
          })
        }
      </div>
    );
  }
}


ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>