reactjs - 在 React JS 中粘贴到多个输入字段

标签 reactjs react-hooks

我在尝试弄清楚如何将值粘贴到多个输入字段中时遇到问题。我基本上正在构建一个验证屏幕,其中有 6 个单独的输入,最大长度为 1,并且希望能够粘贴整个 6 位代码,以便填充所有 6 个输入。我在 Jquery 中找到了几个解决方案,但不太确定如何在 React 中实现它。这是我的代码。

const Verify = ({ handleSubmit, method, rec, changeInput }) => {
    const navigate = useNavigate();
    const { email, phone } = rec
    const send = method === 'email' ? { email: email } : { phone: phone }

    const renderContent = () => {
        const methodLabel = method === 'email' ? 'email address' : 'phone number'

        return (
            <>
            <div id="back-grad"/>
            <div className="col-md-8">
                <div className='verify-text-section'>
                <p className="verify-text pb-5">
                Enter the PIN number we just sent to your {methodLabel}.
                </p>
                </div>
                <div className="flex">
                    <input name='code-1' className='code-input mr-2' autoFocus maxLength='1' onChange={changeInput} />
                    <input name='code-2' className='code-input mr-2' maxLength='1' onChange={changeInput} />
                    <input name='code-3' className='code-input mr-2' maxLength='1' onChange={changeInput} />
                    <input name='code-4' className='code-input mr-2' maxLength='1' onChange={changeInput} />
                    <input name='code-5' className='code-input mr-2' maxLength='1' onChange={changeInput} />
                    <input name='code-6' className='code-input mr-2' maxLength='1' onChange={changeInput} />
                </div>
                <div className="verify-resend mt-3" onClick={resendPin}>Resend Code</div>
                <div className="flex margin-set text-center">
                    <button className="btn btn-block text-white verify-btn">
                        <p className="verify-btn-text">VERIFY</p>
                        </button>
                </div>
            </div>
            </>
        )
    }

    return (
        <>
            {rec.email.length < 1 && rec.phone.length < 1 ? <Navigate to={'/auth'} />
                :
                <div className="d-flex align-items-center h-full">
                    <form className="container" onSubmit={e => onFormSubmit(e, handleSubmit)}>
                        <div className="row justify-content-center">
                            {renderContent()}
                        </div>
                    </form>
                </div>
            }
        </>
    )
}

这里是changeInput函数和handleChange函数,以及传递给组件的rec。

const [rec, setRec] = useState({
        accept: false,
        email: '',
        phone: '',
        pin: [],
    })

    const changeInput = (e) => {
        const { maxLength, name, value } = e.target;
        const [fieldName, fieldIndex] = name.split('-')

        if(value.length >= maxLength) {
            if(parseInt(fieldIndex, 10) < numOfFields) {
                const nextSibling = document.querySelector(`input[name=${fieldName}-${parseInt(fieldIndex, 10) + 1}]`)
                if(nextSibling !== null) {
                    nextSibling.focus()
                }
            }
            setRec({
                ...rec,
                pin:[...rec.pin, value]
            })
        }
    }

    const handleChange = (name, value) => {
        if (name === 'mobile') name = 'phone'
        const recState = {
            ...rec,
            [name]: value,
        }
        setRec(recState)
    }

如有任何帮助,我们将不胜感激。

最佳答案

不要在 React 组件中使用 document.querySelectordocument.querySelectorAll 。相反,将这些元素直接添加到您的组件中。

这是一个使用 paste event 的最小可验证示例。 运行下面的示例并将 4 位数字粘贴到任意输入中。

function App() {
  const [segments, setSegments] = React.useState(["","","",""])
  function onPaste(event) {
    const pasted = event.clipboardData.getData("text/plain")
    setSegments(pasted.split("").slice(0, segments.length))
  }
  function randomPin() {
    return Math.floor(Math.random() * 9000) + 1000
  }
  return <div>
    <p>Copy <b>{randomPin()}</b> and paste into any input</p>
    {segments.map((s, key) =>
      <input key={key} value={s} onPaste={onPaste} />
    )}
    <pre>{JSON.stringify(segments)}</pre>
  </div>
}

ReactDOM.render(<App/>, document.querySelector("#app"))
input { width: 2rem; }
pre { padding: 0.5rem; background-color: #ffc; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

在上面的程序中,无法手动输入 PIN。通过添加onChange事件,可以支持手动录入。不要忘记在 onPaste 处理程序中使用 event.preventDefault,否则所有值都将粘贴到单个段中。

function randomPin() {
  return Math.floor(Math.random() * 9000) + 1000
}

function App({ pin }) {
  const [segments, setSegments] = React.useState(["","","",""])
  function onPaste(event) {
    event.preventDefault()  // ✅
    const pasted = event.clipboardData.getData("text/plain")
    setSegments(pasted.split("").slice(0, segments.length))
  }
  function update(index) { return event => 
    setSegments([
      ...segments.slice(0, index),
      event.target.value,
      ...segments.slice(index + 1)
    ])
  }
  return <div>
    <p>Enter <b>{pin}</b> manually or copy/paste into any input</p>
    {segments.map((s, key) =>
      <input key={key} value={s} onPaste={onPaste} onInput={update(key)} />
    )}
    {segments.join("") == pin ? "✅" : "❌"}
    <pre>{JSON.stringify(segments)}</pre>
  </div>
}

ReactDOM.render(<App pin={randomPin()}/>, document.querySelector("#app"))
input { width: 2rem; }
pre { padding: 0.5rem; background-color: #ffc; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

关于reactjs - 在 React JS 中粘贴到多个输入字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71255377/

相关文章:

javascript - react Hook : new state value not reflecting in setInterval callback

reactjs - react : declaration merging for react-table types doesn't work. 类型 'TableInstance' 上不存在属性

reactjs - 当 child.shouldComponentUpdate() 返回 false 时,React useState() 钩子(Hook)不会更新状态

javascript - 处理受引用影响的状态的 react 方式是什么

javascript - 如何删除所有数据并使用useEffect在不刷新的情况下更新页面

reactjs - onClick 未在 React.js 输入单选按钮上触发

javascript - ReactJs 在使用 api/服务器套接字后加载 div

javascript - react 钩子(Hook) : handle multiple inputs

javascript - Redux - 在 React 组件的构造函数中使用 bindActionCreators 有什么缺点吗?

javascript - 刷新时保持状态