1

I have a number of fields which are produced from arrays dynamically and are bound to a redux state branch. The input value is correctly mapped to the state, then back to component. The problem is it loses focus, you have to re click the input element. I tried to work around this by auto focusing the last updated field, but it focuses at the beginning of the text so that you would write backwards. I looked for solutions to that problem but they all require working directly on the dom or using "onFocus="this.value=value" which as a jsx attribute will not work.

Is there something I'm doing wrong here? Why doesn't react remember the field to be focused automatically as it does with static jsx input elements?

Here is the code which produces the fields:

const renderFields = (fields, target) => {
    if(!fields) return <div></div>
    return fields.map(field => {
      let input = []
      if(field.type==="text") {
        input.push(<input key={generateUID()} type="text" onChange={e=>onChange(field, e.target.value, target)} autoFocus={field.hasFocus} value={field.value} />)
      } else if(field.type==="radio") {
        let values = field.control.match(/\[(.+)\]/)[1].split(",")
        input = values.map(value => {
          return (<label key={generateUID()}><input name={field.id} onChange={e=>onChange(field, value, target)} type="radio" value={value} key={generateUID()} style={{display: "inline-block"}} /> {value}</label>)
        })
      }
      return (
        <div key={generateUID()}>
          <label>{field.label}</label>
          <br />
          {input}
        </div>
      )
    })
  }

I appreciate any help

micahblu
  • 4,924
  • 5
  • 27
  • 33
  • 1
    You could try something like this to get the `onFocus` snippet to work in JSX : ` this.input = ref } onFocus={() => this.input.value = field.value} />` – Chase DeAnda Sep 05 '17 at 22:29
  • 1
    You might want to check out [**this post**](https://stackoverflow.com/questions/28329382/understanding-unique-keys-for-array-children-in-react-js/43892905#43892905) regarding keys and how they work. – Chris Sep 05 '17 at 22:42

2 Answers2

5

I think the problem is that generateUID() is producing unique output each time it is called, forcing React to rebuild that field in the virtual DOM. Generally speaking, you should not randomly generate keys. One possibility is to use the input index as a candidate key:

fields.map(field => {
  ...
  input = values.map((value, inputIdx) => {
     return (
      <label key={generateUID()}>
        <input 
           name={field.id} 
           onChange={e=>onChange(field, value, target)} 
           type="radio" 
           value={value} 
           key={`fieldInput-${inputIdx}`} 
           style={{display: "inline-block"}} /> 
        {value}
      </label>
    )
  })
})
Rob M.
  • 35,491
  • 6
  • 51
  • 50
1

The problem is that you're generating UIDs for your keys, so when React re-renders the components they always have new keys. Try using a key that is defined in some other way, that will be consistent through a re-render.

James Gentes
  • 7,528
  • 7
  • 44
  • 64