受控输入onChange事件仅触发一次-反应

时间:2019-03-23 03:16:21

标签: javascript reactjs

仅注册一次按键,然后输入失去焦点,但是我可以单击返回组件并添加...一个字符。状态已更新。

由于子组件是无状态的,所以我假设只需按照文档中的说明将处理程序作为props传递就足够了,但是从更改方法的绑定到添加构造函数的所有操作都产生了相同的结果。我通常可以在网站上找到答案,但是这次没有运气。

const list = [
  {
    id : 0,
    title : "Went well",
    showCard : false,
    cards : [],
    color : "pink"
   },
   {
    id : 1,
    title : "To Improve",
    showCard : false,
    cards : [],
    color : "yellow"
  },
  {
    id : 2,
    title : "Action Items",
    showCard : false,
    cards : [],
    color : "blue"
  }
]


class App extends Component {

  state = {list : list, usrInpt : ""}

  handleChange = e => {this.setState({usrInpt:e.target.value})}

  add = e => {
    e.preventDefault()
    let updatedList = this.state.list.map(obj => {
      if(obj.id == e.target.id) 
this.state.list[obj.id].cards.push(this.state.usrInpt)
      return obj
    })
    console.log("uL",updatedList)
    this.setState({list:updatedList}) 
    //this.setState(this.state.list[e.target.id].cards = [...this.state.list[e.target.id].cards,"pp"])
  }

  render() {
    return (
      <div className="App">
        <h2>Metro Board</h2>
        <ul className="container">
        {this.state.list.map((item) =>
            <List key={(Math.random() * 1)} text={item.title}
                    id={item.id} cards={item.cards} color={item.color} 
                    usrInpt={this.state.usrInpt} add={this.add} handleChange={this.handleChange}/>
        )}
        </ul>
      </div>
    )
  }
}

const List = (props) =>{

return(
<li>
    <h3>{props.text}</h3>
    <ul className="stack">
    <li><button id={props.id} type="button" className="block" onClick={e =>props.add(e)}>+</button></li>
    {props.cards.map((card,i)=> {
        console.log("card",card)
        return <ListItem key={(Math.random() * 1)}
                    idx={i}
                    color={props.color}
                    handleChange={props.handleChange}
                    usrInpt={props.usrInpt}/>
        })}
    </ul>
</li>
)

}

const ListItem = (props) =>{
    console.log("card props and value",props)
    return <li>
            <div className="card" style={{backgroundColor: props.color}}>
              <textarea type="text"
                    className="card"
                    placeholder="Enter text here"
                    value={props.usrInpt}
                    onChange={e => props.handleChange(e)}>
              </textarea>
          <div><a className="ltCtl" href="./logo" onClick={e => console.log(e)}>&lt;</a>
               <a className="clCtl" href="./logo" onClick={e => console.log(e)}>x</a>
               <a className="rtCtl" href="./logo" onClick={e => console.log(e)}>&gt;</a>
          </div>
        </div>
       </li>
  }

List和&ListItem都是单独的文件...任何帮助都将非常有用。谢谢。

2 个答案:

答案 0 :(得分:1)

更新:

我能够与一个专职开发人员联系,似乎我试图通过创建唯一的密钥来搞砸:

  

密钥需要保持一致,但是在这种情况下,每次都使用不同的值   React在标识哪个元素所关注的元素时使用键,但是在这种情况下,它与上一个渲染不同。所以React不知道该关注什么。如果您使用带有循环索引的字符串,或者使用存储在循环外部(例如在状态中)的ID,则可以具有唯一键。   它确实需要是唯一的,但也需要保持一致。

代码如下:

      return (
        <Card
          key={Math.random() * 1} // <--- Don't!!
          idx={i}
          color={props.color}
          handleChange={props.handleChange}
          usrInpt={props.usrInpt}
        />
      );

导致React失去对渲染内容的跟踪,因为每个渲染键都在变化。如果使用循环,则首选方法是使用带有标识符和索引的字符串插值:

return(
<li>
    <h3>{props.text}</h3>
    <ul className="stack">
    <li><button id={props.id} type="button" className="block" onClick={e =>props.add(e)}>+</button></li>
    {props.cards.map((card,i)=> {
        console.log("card",card)
        return <Card key={`card-column-${props.id}-${i}`}
                    idx={i}
                    color={props.color}
                    handleChange={props.handleChange}
                    usrInpt={props.usrInpt}/>
        })}
    </ul>
</li>
)

还有 ,它是@miyu ...我未测试的评论。倾听您的同伴和导师的声音……追逐错误不会浪费您12个小时。谢谢。

答案 1 :(得分:0)

state是非分层的。这意味着,当您更新状态的子对象但父对象未更新时,则react不会触发componentDidChange。 尝试添加一个在列表更新时会更新的计数器。

add = e => {
    e.preventDefault()
    let updatedList = this.state.list.map(obj => {
      if(obj.id == e.target.id) 
this.state.list[obj.id].cards.push(this.state.usrInpt)
      return obj
    })
    console.log("uL",updatedList)
    let counter = this.state.counter || 0;
    this.setState({list:updatedList, counter: counter++}) 
    //this.setState(this.state.list[e.target.id].cards = [...this.state.list[e.target.id].cards,"pp"])
  }