繁体   English   中英

如何处理React中动态创建的受控输入?

[英]How to deal with dynamically created controlled inputs in React?

因此,我一直在尝试创建多个动态创建的受控输入。 但是,如果我按add ingredient按钮add ingredient输入,则在向其添加文本时,新创建的输入不会保持焦点。
奇怪的事情(或线索)是在添加新的输入后,第一个输入仍会保持焦点,只是添加的输入不能正常工作。

为了清楚起见,我以伪代码格式提出了问题:

if(Not react way of creating multiple dynamically created controlled inputs) {  
 question = How to create multiple dynamically created controlled inputs in React way?  
} else {  
 question = How to make the dynamically created input retain focus?  
}

代码是(工作jsfiddle片段):

 class Modal extends React.Component { constructor(props){ super(props) this.state = { ingredients: [{ value: 'aap'}] } } addIngredient(e) { const old = this.state.ingredients const newState = [...old, {value: ''}] this.setState( {ingredients: newState} ) } handleInput(e, i) { console.log(e.target.value) var newState = this.state.ingredients newState[i].value = e.target.value /*var promise = new Promise( (resolve, reject) => { return this.setState({ ingredients: newState}) }) promise.then( () => {return e.target.focus()} ) */ this.setState( { ingredients: newState } ) e.target.focus() } render() { const inputs = this.state.ingredients return ( <div className="modal"> <div className="modal-box"> <form> <h1>Create your recipe</h1> <div> <label>Recipe name:</label> <input type="text" /> </div> <div> <label>Ingredients:</label> {inputs.map( (input, i) => ( <input value={input.value} onChange={(e) => this.handleInput(e, i)} key={`${i}-${i * Math.random()}`} /> ))} <button id="ingredient-button" type="button" onClick={(e) => this.addIngredient(e)}><span>+</span>add ingredient</button> </div> </form> </div> </div> ); } } ReactDOM.render(<Modal/>, 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> 

由于您的密钥是用随机数生成的,因此每次DOM重新呈现时,它都不会将其识别为相同的输入,因此会失去焦点。 我将密钥更改为以下内容以使其正常工作。

key={`ingredients-${i}`}

 class Modal extends React.Component { constructor(props){ super(props) this.state = { ingredients: [{ value: 'aap'}] } } addIngredient(e) { const old = this.state.ingredients const newState = [...old, {value: ''}] this.setState( {ingredients: newState} ) } handleInput(e, i) { var newState = this.state.ingredients newState[i].value = e.target.value /*var promise = new Promise( (resolve, reject) => { return this.setState({ ingredients: newState}) }) promise.then( () => {return e.target.focus()} ) */ this.setState( { ingredients: newState } ) } render() { const inputs = this.state.ingredients return ( <div className="modal"> <div className="modal-box"> <form> <h1>Create your recipe</h1> <div> <label>Recipe name:</label> <input type="text" /> </div> <div> <label>Ingredients:</label> {inputs.map( (input, i) => ( <input value={input.value} onChange={(e) => this.handleInput(e, i)} key={`ingredients-${i}`} /> ))} <button id="ingredient-button" type="button" onClick={(e) => this.addIngredient(e)}><span>+</span>add ingredient</button> </div> </form> </div> </div> ); } } ReactDOM.render(<Modal/>, 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> 

归功于Nelson Yeung ,他找到了带有键的bug。 但是,也要专注于每个创建的输入,它有助于使它们成为自己的类组件。 这样,您就可以访问生命周期方法。 它们可能仍然受到控制,但是它们将把onChange回调作为道具传递给他们。

我将refcomponentDidMount()一起使用,以将新组件恰好聚焦一次(仅在第一次安装时)。

class Input extends React.Component {
    constructor(props){
    super(props);
    this.ref = null;
  }
  componentDidMount(){
    this.ref.focus();
  }
  render(){
    const {value, handleOnChange} = this.props
    return <input value={ value } onChange={ handleOnChange } ref={ el => this.ref = el} />
  }
}

class Modal extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      ingredients: [{ value: 'aap'}]
    }
  }
  addIngredient(e) {
    const old = this.state.ingredients
    const newState = [...old, {value: ''}];

    this.setState(
      {ingredients: newState}
    )
  }
  handleInput(i) {
  // return callback with the right index
    return (e) => {
      var newState = this.state.ingredients
      newState[i].value = e.target.value
      this.setState( { ingredients: newState } )
    }
  }

  render() {
    const inputs = this.state.ingredients
    return (
      <div className="modal">
        <div className="modal-box">
          <form>
            <h1>Create your recipe</h1>
            <div>
              <label>Recipe name:</label>
              <input type="text" />
            </div>
            <div>
            <label>Ingredients:</label>
            {inputs.map( (input, i) => (
              <Input 
                value={input.value} 
                handleOnChange={this.handleInput(i)} 
                key={i}
              />
            ))}
              <button id="ingredient-button" type="button" onClick={(e) => this.addIngredient(e)}><span>+</span>add ingredient</button>
            </div>
          </form>

        </div>
      </div>
    );
  }
}

ReactDOM.render(<Modal/>, document.getElementById('root'))

此处的工作代码示例: https : //jsfiddle.net/jonahe/2ga02g6h/

编辑 :我现在意识到我可能已经读过你的问题太快了。 也许您不需要/想要/询问新创建的输入字段。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM