【问题标题】:React Hooks only update state on form submitReact Hooks 仅在表单提交时更新状态
【发布时间】:2019-11-29 21:11:11
【问题描述】:

所以我整个上午都在忙,不知道如何使用useState 正确更新我的状态。

我有一个带有name 的受控用户输入。当用户输入文本并提交时,我想获取输入值并将其推送到另一个状态对象 namesList 并映射到子组件中的该数组。

父组件

import React, { Fragment, useState } from 'react';

import TextField from '@material-ui/core/TextField';

import NameInputList from './NameInputList';

const NameInputContainer = () => {
  const [name, setName] = useState('');
  const [namesList, setNamesList] = useState([]);

  const handleChange = event => {
    const { value } = event.target;
    setName(value);
  };

  const handleSubmit = event => {
    event.preventDefault();
    setNamesList(prevState => [...prevState, name]);
    setName('');
  };

  return (
    <Fragment>
      <form onSubmit={handleSubmit}>
        <TextField
          id="name"
          label="Enter New Name"
          variant="outlined"
          value={name}
          onChange={handleChange}
        />
      </form>
      {namesList.length > 0 && <NameInputList names={namesList} />}
    </Fragment>
  );
};

export default NameInputContainer;

子组件

import React from 'react';
import PropTypes from 'prop-types';

const NameInputList = ({ names }) => {
  console.log('child component names: ', names);
  const generateKey = val => {
    return `${val}_${new Date().getTime()}`;
  };

  return (
    <ul>
      {names.map((name, index) => ( // <--- Adding the index here seems to resolve the problem. I want to say the error was happening based on issues with having Unique keys. 
        <li key={generateKey(name + index)}>{name}</li>
      ))}
    </ul>
  );
};

NameInputList.propTypes = {
  names: PropTypes.arrayOf(PropTypes.string)
};

NameInputList.defaultProps = {
  names: []
};

export default NameInputList;

似乎当我第一次提交子组件获得正确的值并按预期​​呈现时。当我输入一个新名称时,每个handleChange 都会重新呈现。我不确定如何始终如一地:输入文本 > 提交输入 > 更新 namesList > 在子组件中呈现更新的 namesList,而 handleChange 不会破坏功能。

【问题讨论】:

  • 我们应该看看里面有什么NameInputList^^
  • 重新渲染将发生,因为 namesList 的新副本将作为道具提供,即使其内容没有改变。你能分享NameInputList的代码吗?
  • 对不起,我想我明白了,当我向地图添加索引时,它按预期工作。我认为它按预期工作,这是我无法理解的。

标签: javascript reactjs react-hooks


【解决方案1】:

再补充一点,因为namesList prop 是一个数组,每个父级重新渲染都会发送一个新副本。因此,它的比较总是错误的,React 会触发子元素的重新渲染。

您可以通过这样做来防止重新渲染:

export default React.memo(NameInputList, function(prevProps, nextProps) {
  return prevProps.names.join("") === nextProps.names.join("");
});

这将确保 NameInputList 仅在 namesList 的内容实际更改时重新渲染。

【讨论】:

  • 我喜欢这个解决方案将我带到哪里,查找备忘录看起来很有希望。不幸的是,我仍然遇到独特的关键错误。我已经删除了 index 参数,并且没有在 generateKey() 中使用它。现在我有export function NameInputList({ names }) {...} const MemoizedNameInputList = React.memo(NameInputList, (prevProps, nextProps) =&gt; {return prevProps.names.join('') === nextProps.names.join('');}); export default MemoizedNameInputList; 但我不确定如何解决唯一键错误。 idk 如果 NPM 包 shortid 是一个合适的解决方案
  • 理想情况下,只需将密钥作为${name}_${index} 传递就足够了。这将永远是独一无二的
猜你喜欢
  • 2019-09-15
  • 2019-11-11
  • 1970-01-01
  • 2019-08-08
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 2020-12-28
相关资源
最近更新 更多