简体   繁体   English

使用虚拟键盘时 useState 的初始值未更新

[英]Initial value for useState isn't updating when using Virtual Keyboard

Beginner here.初学者在这里。 Trying to get react-simple-keyboard working with Gatsby & React.试图让react-simple-keyboard与 Gatsby & React 一起工作。

I initialise my form with some state ( firstName: "Johnn" ).我用一些 state ( firstName: "Johnn" ) 初始化我的表单。 This should be the initial state.这应该是最初的 state。 I want the user to be able to modify this name, and save the modified version in state.我希望用户能够修改此名称,并将修改后的版本保存在 state 中。

I initialise my state here:我在这里初始化我的 state:

 const [inputs, setInputs] = useState({
     firstName: "Johnn"
  })

When I click on the field and press a button on the virtual keyboard (a letter, say), it deletes the content of the whole field and puts the letter there, instead of adding the letter to whats already in there.当我单击该字段并按下虚拟键盘上的一个按钮(例如一个字母)时,它会删除整个字段的内容并将字母放在那里,而不是将字母添加到那里已经存在的内容中。 Also: Clicking on the field and pressing backspace (on the react-simple-keyboard) does not do anything.另外:单击该字段并按退格键(在 react-simple-keyboard 上)不会执行任何操作。 Why is this?为什么是这样?

import React, { useRef, useState, useContext, useEffect } from "react"
import styled from "styled-components"
import ReactDOM from "react-dom"
import Keyboard from "react-simple-keyboard"
import "react-simple-keyboard/build/css/index.css"
import Layout from "@components/layout"
import { useForm } from "react-hook-form"
import { Flex, Box } from "rebass/styled-components"
import Input from "@atoms/Input"

import {
  GlobalDispatchContext,
  GlobalStateContext,
} from "../context/GlobalContextProvider"

function App() {
  const dispatch = useContext(GlobalDispatchContext)
  const state = useContext(GlobalStateContext)

  const [inputs, setInputs] = useState({
    firstName: "Johnn",
    // firstName: state.customers[state.currentCustomer].firstName,
  })
  const [layoutName, setLayoutName] = useState("default")
  const [inputName, setInputName] = useState("default")

  const [isShiftPressed, setShiftPressed] = useState(false)
  const [isCaps, setCaps] = useState(false)
  const [isKeyboardVisible, setKeyboardVisible] = useState(false)

  const { register, handleSubmit, errors } = useForm()
  const keyboard = useRef()

  const onChangeAll = newInputs => {
    /**
     * Here we spread the inputs into a new object
     * If we modify the same object, react will not trigger a re-render
     */
    setInputs({ ...newInputs })
  }

  const handleShift = () => {
    const newLayoutName = layoutName === "default" ? "shift" : "default"
    setLayoutName(newLayoutName)
  }

  const onKeyPress = button => {
    if (isShiftPressed === true && !isCaps) {
      setShiftPressed(false)
      handleShift()
    }
    if (button === "{lock}") {
      setCaps(true)
    }
    if (button === "{shift}" || button === "{lock}") {
      setShiftPressed(true)
      handleShift()
    }
  }

  const onChangeInput = event => {
    const inputVal = event.target.value

    setInputs({
      ...inputs,
      [inputName]: inputVal,
    })

    keyboard.current.setInput(inputVal)
  }

  const getInputValue = inputName => {
    return inputs[inputName] || ""
  }

  return (
    <Layout>
      <Flex flexDirection="column" style={{ height: "100%" }}>
        <form onSubmit={handleSubmit(onSubmit)}>
          <Input
            id="firstName"
            name="firstName"
            value={getInputValue("firstName")}
            onFocus={() => {
              setInputName("firstName")
            }}
            placeholder={"First Name"}
            onChange={onChangeInput}
          />
        </form>

        <Keyboard
          keyboardRef={r => (keyboard.current = r)}
          inputName={inputName}
          layoutName={layoutName}
          onChangeAll={onChangeAll}
          onKeyPress={onKeyPress}
        />
      </Flex>
    </Layout>
  )
}

export default App

You might need to use useEffect hook set the initial keyboard value, and on subsequent changes and also remove keyboard.current.setInput(inputVal) .您可能需要使用 useEffect 挂钩设置初始键盘值,并在随后的更改中删除keyboard.current.setInput(inputVal)

const {firstName} = input;
useEffect(() => {
  keyboard.current.setInput(firstName);
}, [firstName]);

This will make sure that the initial and subsequent changes of firstName is set in keyboard instance.这将确保在键盘实例中设置 firstName 的初始和后续更改。

Code Sandbox: https://codesandbox.io/s/distracted-aryabhata-j3whs?file=/src/index.js代码沙箱: https://codesandbox.io/s/distracted-aryabhata-j3whs?file=/src/index.js

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

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