javascript React将默认值添加到不受控的MUI文本字段

c0vxltue  于 2023-02-18  发布在  Java
关注(0)|答案(1)|浏览(98)

我使用的是React 17和Mui 5。我的表单页面存在延迟问题,因为所有文本字段都是受控的,如果我有一个很长的表单,并且我在键盘上键入的速度非常快,onChange事件将被多次触发,每次都会重新加载渲染,因为我的handleChange中有this.setState()
所以我有个主意,这是通过移除props value并将debounce添加到handleChange函数来设置我的所有文本字段不受控制。它工作正常,但我在编辑表单时遇到了一个问题。我必须从json response中获取当前值并在我的文本字段中设置此值,但我不再有props value。所以我可以使用props defaultValue,但是这个props的问题是它只会被设置一次,所以在第一次渲染时我会得到空值,在第二次渲染时(json响应后)我会得到值,但是defaultValue总是空的,因为第二次渲染被忽略了。
然后我发现的唯一使它工作的方法是只在设置值时显示文本字段:

{this.state.my_var || hasGotJsonResponse && (
                <TextField
                  label="Label"
                  name="my_var"
                  onChange={this.handleChange}
                  defaultValue={this.state.my_var}
                />
              )}

这个方法很有效,但是我不喜欢只在特定的情况下显示这个字段。有别的方法可以解决我的问题吗?或者有一种方法可以动态初始化defaultProps
注意:我不想使用ref,至少有一种简单的方法可以在多个输入上管理它

    • 编辑**

我给你看一个简单的代码片段。试着快速输入,你会注意到文本域中的滞后
x一个一个一个一个x一个一个二个x

j7dteeu8

j7dteeu81#

问题是 * 当其中一个输入发生更改 * 时,您的每个输入都将重新渲染。当您更改field_0并更新值时,由于它们都共享state,因此它们都将在当前设置中重新渲染。
我把你的代码片段和简单的记录渲染。尝试键入一个字母在第一次输入,并观看所有其他99个输入重新渲染。

const inputFieldKeys = Array.from({
  length: 100
}).map((e, i) => "field_" + i.toString());

const App = (props) => {
  const [inputState, setInputState] = React.useState({});

  // this runs fine even without the `useCallback` optimization, at least for me
  const handleChange = React.useCallback((e) => {
    setInputState(oldState => ({ ...oldState,
      [e.target.name]: e.target.value
    }));
  }, [setInputState]);
  
  const InputLogged = ({ name,  value, onChange, label }) => {
    console.log(`${name} input re-rendered`);
    return (<MaterialUI.TextField name={name} key={name} value={inputState[name] || ""} onChange={handleChange}
      label={name}/>);
  };
  
  return ( <div>
      {inputFieldKeys.map(key=>(
      <InputLogged name={key} key={key} value={inputState[key] || ""} onChange={handleChange}
      label={key} />
    ))}
  </div>
  );
};

ReactDOM.render( < App / > , document.getElementById("root"));
<div id="root"></div>
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script crossorigin src="https://unpkg.com/@mui/material@5/umd/material-ui.production.min.js"></script>

关键是告诉每个输入组件 * 何时应该使用React memo重新呈现 *。
这是你的代码片段,做了一些小的修改。现在每个Input只在它自己的值改变时重新呈现。
一个二个一个一个
看一看我创建的this sandbox demonstration,它有助于更好地理解memo,以及当state发生变化时,它如何与组件重新呈现相关。
另外,如果你必须使用class component,记忆化可以用PureComponent来处理,这实现了componentDidUpdate,它对 prop 做了一个肤浅的比较,只有当它们改变时才重新渲染。
只需使用:
class Greeting extends PureComponent {}

相关问题