文本内容未在反应中更新

时间:2020-05-25 11:01:27

标签: javascript reactjs

我将类组件重写为功能组件,因为必须使用react钩子。现在,除了屏幕外,其他所有功能都可以正常工作。它不更新文本。我已经添加了一个引用到称为screen element的元素,并且函数setScreenText似乎起作用。我放了一些日志,它们返回了我对它们的期望。如果我按5键,console.log(screenElement.textContent)返回5,console.log(screenElement)返回{current: div.screen, textContent: "5"}唯一的问题仍然是它没有更新屏幕上的文本,因此保持空白。

import React, {useRef, useState} from 'react';
import '../style/App.scss';
import {UPDATE_GAME_STATE} from '../actions';
import { useDispatch } from 'react-redux';

function Keypad() {
    const dispatch = useDispatch();

    const KEYPAD_STATE_SUCCESS = "keypad_success";
    const KEYPAD_STATE_FAILED = "keypad_failed";
    const KEYPAD_STATE_INPUT = "keypad_input";

    const [state, setState] = useState(KEYPAD_STATE_INPUT);
    const tries = [];
    const screenElement = useRef(null);

    const handleKeyPress = async(value) => {

        tries.push(value);

        setScreenText(tries.join(''));

        if (tries.length >= 4) {
            const success = await tryKeyCode(tries.join(''))

            const newState = {
                setState: success ? KEYPAD_STATE_SUCCESS : KEYPAD_STATE_FAILED
            }

            const screenText = success ? "SUCCESS" : "FAILED";
            const textScreenTime = success ? 3000 : 1000;
            const handleGameState = success ? () => onSuccess() : () => onFailed();

            setTimeout(() => {
                setScreenText(screenText);

                setTimeout(handleGameState, textScreenTime);
            }, 200);

            setState(newState);
        }
    }

    const onSuccess = () => {
        dispatch(UPDATE_GAME_STATE('completed'))
    }

    const onFailed = () => {
        console.log("wrong code")
    }

    /**
     * @param {string} text
     */
    const setScreenText = (text) => {
        screenElement.textContent = text;
        console.log(screenElement.textContent); // if key 5 is pressed returns 5
        console.log(screenElement); // returns {current: div.screen, textContent: "5"}
    }

    /**
     * @param {string} code
     * @returns boolean
     */
    const tryKeyCode = async(code) => {
        const response = (await fetch("http://localhost:3000/keypad", {
            method: "POST",
            body: JSON.stringify({
                "code": code
            }),
            headers: {
                "Content-Type": "application/json"
            }
        }));

        return response.status === 200;
    }

    const keys = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    const Key = ({number, className = ""}) => <button className={"key " + className} onClick={() => handleKeyPress(number)}>{number}</button>
    const keyElements = keys.map(key => (<Key number={key}/>))

    return (
        <div className="keypad_wrapper">
            <div className="screen" ref={screenElement}/>
            {keyElements}
            <Key className="last" number={0}/>
        </div>
    );
}

export default Keypad;

1 个答案:

答案 0 :(得分:1)

如react docs中所述:

useRef返回一个可变的ref对象,该对象的.current属性已初始化为传递的参数(initialValue)。返回的对象将在组件的整个生命周期中保持不变。

因此,无需更新screenElement.textContent,而是需要像这样更新screenElement.current.textContent

const setScreenText = (text) => {
  if (screenElement.current) {
    // Wait until current is available
    // `current` points to the mounted element
    screenElement.current.textContent = text;
    console.log(screenElement.current);
  }
}