Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
500 views
in Technique[技术] by (71.8m points)

javascript - React Hooks仅在表单提交时更新状态(React Hooks only update state on form submit)

So I've been at this all morning and can't figure out how to update my state correctly using useState .(所以我useState都在这里,无法弄清楚如何使用useState正确更新我的状态。)

I have a single controlled user input with name .(我有一个name受控用户输入。)

When a user enters text and submits I would like to take the input value and push that to another state object namesList and map over that array in a child component.(当用户输入文本并提交时,我想获取输入值并将其推到另一个状态对象namesList并映射到子组件中的该数组。)

Parent Component(父组件)

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;

Child Component(子组件)

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;

Seems like when I submit the first time the child component gets the correct value and renders as expected.(好像是我第一次提交子组件时获得正确的值并按预期??方式呈现。)

When I go to input a new name there's a rerender on every handleChange .(当我输入新名称时,每个handleChange上都会有一个重新渲染。) I'm not sure how to consistently: enter text > submit input > update namesList > render updated namesList in child component without handleChange breaking the functionality.(我不确定如何一致:在子组件中输入文本>提交输入>更新namesList >呈现更新的namesList ,而handleChange破坏功能。)

在此处输入图片说明

  ask by Full-Hybrid translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Just adding to that, as namesList prop is an array, a new copy will be sent for each parent re-render.(只是添加了一点,因为namesList是一个数组,所以将为每个父级重新渲染发送一个新副本。)

Hence it's comparison will always be false and React will trigger a re-render of the child.(因此,它的比较将始终为false,并且React将触发子对象的重新渲染。)

You can prevent the re-render by doing this :(您可以通过执行以下操作防止重新渲染:)

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

This will ensure that NameInputList only re-renders when the contents of namesList actually change.(这将确保NameInputList仅在namesList的内容实际更改时才重新渲染。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...