改变状态时输入值不更新

时间:2021-07-19 16:08:16

标签: reactjs typescript state

在创建一个用于学习目的的小项目时,我遇到了更新输入值的问题。这是组件(我已尝试将其减少到最低限度)。

function TipSelector({selections, onTipChanged}: {selections: TipSelectorItem[], onTipChanged?:(tipPercent:number)=>void}) {
    
    const [controls, setControls] = useState<any>([]);
    const [tip, setTip] = useState<string>("0");

    function customTipChanged(percent: string)  {
        setTip(percent);
    }

    //Build controls
    function buildControls()
    {
        let controlList: any[] = [];
        controlList.push(<input className={styles.input} value={tip.toString()} onChange={(event)=> {customTipChanged(event.target.value)}}></input>);
        setControls(controlList);
    }
    
    useEffect(()=>{
        console.log("TipSelector: useEffect");
        buildControls();

        return ()=> {
            console.log("unmounts");
        }
    },[])
    
    console.log("TipSelector: Render -> "+tip);
    return (
        <div className={styles.tipSelector}>
            <span className={globalStyles.label}>Select Tip %</span>
            <div className={styles.btnContainer}>
                {
                   controls
                }
            </div>
        </div>
    );
}

如果我将输入的创建直接移到 return() 语句中,则值会正确更新。

2 个答案:

答案 0 :(得分:2)

我会将您的输入移出该组件,让它们从 TipSelector 中管理自己的状态。

见:

https://codesandbox.io/s/naughty-http-d38w9

例如:

import { useState, useEffect } from "react";
import CustomInput from "./Input";

function TipSelector({ selections, onTipChanged }) {
  const [controls, setControls] = useState([]);

  //Build controls
  function buildControls() {
    let controlList = [];
    controlList.push(<CustomInput />);
    controlList.push(<CustomInput />);
    setControls(controlList);
  }

  useEffect(() => {
    buildControls();

    return () => {
      console.log("unmounts");
    };
  }, []);

  return (
    <div>
      <span>Select Tip %</span>
      <div>{controls}</div>
    </div>
  );
}

export default TipSelector;

import { useState, useEffect } from "react";

function CustomInput() {
  const [tip, setTip] = useState("0");

  function customTipChanged(percent) {
    setTip(percent);
  }

  return (
    <input
      value={tip.toString()}
      onChange={(event) => {
        customTipChanged(event.target.value);
      }}
    ></input>
  );
}

export default CustomInput;

答案 1 :(得分:1)

您只调用 buildControls 一次,其中 <input ... 仅获得一次其值。

每当 React 重新渲染您的组件时(例如因为某些状态发生变化),您的 {controls} 都会告诉 React 使用旧值渲染原始 <input ...

我不确定您为什么将控件存储在状态变量中?没有必要,正如你所注意到的,它使事情复杂化了很多。您基本上也需要一个 renderControls() 函数,您可以将 {controls} 替换为。