防止输入字段失去焦点

问题描述 投票:0回答:3

这是一个带有作为组件插入的输入字段的代码示例,输入字段中的每次更改都会失去焦点。似乎当您更改整个组件时会重新渲染,并且那些失去焦点的组件,实现这样的动态表单的最佳实践是什么,以及如何防止此处失去焦点?

PS:这是一个更复杂表单的一部分的小示例,其中表单的每个后续部分都取决于前一个部分的选择。

代码沙盒

import ReactDOM from 'react-dom'
import React, { useReducer } from 'react'
import Select from 'react-select'

const SELECT_UPDATED = 'INPUT_UPDATED'
const TEXT_UPDATED = 'TEXT_UPDATED'
const TEXT_UPDATED2 = 'TEXT_UPDATED2'
const INITIAL_STATE = {
  selectedType: '',
  inputText: '',
  inputText2: ''
}

let reducer = (state, action) => {
  switch (action.type) {
    case SELECT_UPDATED:
      return { ...state, selectedType: action.selectedType }
    case TEXT_UPDATED:
      return { ...state, inputText: action.inputText }
    case TEXT_UPDATED2:
      return { ...state, inputText2: action.inputText2 }
    default:
      return state
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, INITIAL_STATE)
  console.log('state: ', state)

  return (
    <div>
      <Select
        options={[{ value: 'edit_text', label: 'Edit text' }, { value: 'hide_input', label: 'Hide input' }]}
        onChange={e => dispatch({ type: SELECT_UPDATED, selectedType: e.value })}
      />
      <p/>
      <SecondStep />
    </div>
  )

  function SecondStep() {
    if (state.selectedType === 'edit_text') {
      return <div>
        <input type="text" autoFocus value={state.inputText} onChange={e => dispatch({ type: TEXT_UPDATED, inputText: e.target.value })} />
        <input type="text" autoFocus value={state.inputText2} onChange={e => dispatch({ type: TEXT_UPDATED2, inputText2: e.target.value })} />
        </div>
    } else if (state.selectedType === 'hide_input') {
      return <div>Hidden input</div>
    } else {
      return <div>NA</div>
    }
  }
}

ReactDOM.render(<App />, document.getElementById('root'))
reactjs react-hooks
3个回答
1
投票

您可以像这样在输入中使用 autoFocus 属性

<input type="text" autoFocus value={state.inputText} onChange={e => dispatch({ type: TEXT_UPDATED, inputText: e.target.value })} />

更新

我刚刚更改了你的代码,下面我在这里使用了3个输入框

import ReactDOM from 'react-dom'
import React, { useReducer } from 'react'
import Select from 'react-select'

const SELECT_UPDATED = 'INPUT_UPDATED'
const TEXT_UPDATED = 'TEXT_UPDATED'
const TEXT_UPDATED1 = 'TEXT_UPDATED1'
const TEXT_UPDATED2 = 'TEXT_UPDATED2'
const INITIAL_STATE = {
  selectedType: '',
  inputText: '',
  inputText1: '',
  inputText2: '',
  autoFocus1:true,
  autoFocus2:false,
  autoFocus3:false,

}

let reducer = (state, action) => {
  console.log(action.type)
  switch (action.type) {
    case SELECT_UPDATED:
      return { ...state, selectedType: action.selectedType }
    case TEXT_UPDATED:
      return { ...state, inputText: action.inputText, autoFocus1:true, autoFocus2:false, autoFocus3:false }
    case TEXT_UPDATED1:
      return { ...state, inputText1: action.inputText1 , autoFocus1:false, autoFocus2:true, autoFocus3:false }
    case TEXT_UPDATED2:
      return { ...state, inputText2: action.inputText2 , autoFocus1:false, autoFocus2:false, autoFocus3:true }
    default:
      return state
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, INITIAL_STATE)
  console.log('state: ', state)

  return (
    <div>
      <Select
        options={[{ value: 'edit_text', label: 'Edit text' }, { value: 'hide_input', label: 'Hide input' }]}
        onChange={e => dispatch({ type: SELECT_UPDATED, selectedType: e.value })}
      />
      <SecondStep />
    </div>
  )

  function SecondStep() {
    if (state.selectedType === 'edit_text') {
      return (
        <div>
          <input type="text" autoFocus={state.autoFocus1} value={state.inputText} onChange={e => dispatch({ type: TEXT_UPDATED, inputText: e.target.value })} />
          <input type="text" autoFocus={state.autoFocus2} value={state.inputText1} onChange={e => dispatch({ type: TEXT_UPDATED1, inputText1: e.target.value })} />
          <input type="text" autoFocus={state.autoFocus3} value={state.inputText2} onChange={e => dispatch({ type: TEXT_UPDATED2, inputText2: e.target.value })} />
        </div>
      )
    } else if (state.selectedType === 'hide_input') {
      return <div>Hidden input</div>
    } else {
      return <div>NA</div>
    }
  }
}

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

0
投票

如果问题是关于重新渲染的,您可以为组件分配键值,这样状态更新后被视为保留的组件就不会再次被卸载/重新挂载。


0
投票

这是一个永远不会失去焦点的快速技巧

<input
type="text"
autoFocus={true}
onBlur={(e) =>  e.currentTarget?.focus()}/> 
© www.soinside.com 2019 - 2024. All rights reserved.