首页 > 解决方案 > 文本内容未在反应中更新

问题描述

我将我的类组件重写为功能组件,因为我必须使用反应钩子。现在一切正常,除了屏幕。它没有更新文本。我已经向名为 screen 元素的元素添加了一个引用,并且函数 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;

标签: javascriptreactjs

解决方案


如反应文档中所述:

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);
  }
}

推荐阅读