首页 > 解决方案 > onChange 正在重置状态 - useState

问题描述

我对 ReactJs 并不陌生,但不知何故,当我在我的组件函数中 console.log 时,它显示已经设置的属性也被重置了。下面是我完整的功能组件

import React, { useState } from 'react';
import {
  Grid, Typography, Paper, TextField,
} from '@material-ui/core';
import Autocomplete from '@material-ui/lab/Autocomplete';
import SomeComponent from '../../common/SomeComponent';
import countries from '../../utils/countries_data';
import AlertMsg from '../../utils/Alert';
import { MarkRequired } from '../style';

const App = ({ classes, handleNext, handlePay }) => {
  const [contact, setContact] = useState({
    firstName: '',
    lastName: '',
    address1: '',
  });

  const handleChange = (e) => setContact({
    ...contact,
    [e.target.name]: e.target.value,
  });
  console.log('above splitAddressProperties', contact);
  const splitAddressProperties = (data) => {
    console.log('func start', contact);
    const country = countries.filter(
      (count) => count.alpha2 === data.country_code || count.alpha3 === data.country_code,
    );
    setContact({
      ...contact,
      address1: data.address,
      city: data.city,
      zip: data.zip,
      country: country[0],
    });
    console.log('func end', contact);
  };


  return (
    <Grid item xs={12}>
      <Paper className={classes.paper}>
        <Typography className={classes.inputText}>Contact Information</Typography>

        <Grid container style={{ marginBottom: '15px' }}>
          <Grid item xs={6} style={{ paddingRight: '10px' }}>
            <Typography className={classes.inputTitle}>
              First Name
              <MarkRequired>*</MarkRequired>
            </Typography>
            <input
              className={classes.inputsty}
              value={contact.firstName}
              onChange={handleChange}
              type="text"
              name="firstName"
            />
          </Grid>
          <Grid item xs={6} style={{ paddingLeft: '10px' }}>
            <Typography className={classes.inputTitle}>
              Last Name
              <MarkRequired>*</MarkRequired>
            </Typography>
            <input
              className={classes.inputsty}
              value={contact.lastName}
              type="text"
              onChange={handleChange}
              name="lastName"
            />
          </Grid>
        </Grid>
        <Grid style={{ marginBottom: '15px' }}>
          <Typography className={classes.inputTitle}>
            Address
            <MarkRequired>*</MarkRequired>
          </Typography>
          <SomeComponent
            className={classes.inputsty}
            value={contact.address1}
            onChange={splitAddressProperties}
          />
        </Grid>
      
      </Paper>
    </Grid>
  );
};

export default App;

如果我输入名字和姓氏并输入 SomeComponent 值splitAddressProperties被触发,但它显示联系人的值与默认值相同。需要注意的是 console.log('above splitAddressProperties', contact); 输入名字和姓氏时触发两次。

标签: javascriptreactjsreact-hooksuse-state

解决方案


我没有足够的信息来真正找到问题,但我猜测 SomeComponent 存储并使用了 onChange 道具的旧参考。

例如:

const SomeComponent = (props) => {
    // ...
    const innerOnChange = useCallback(
        (data) => {
            props.onChange(data);
        }, 
        // Note that the deps array doesn't have onChange:
        []
    );
    // ...
}

我要做的是从 setState 访问当前联系人:

setContact(currentContact => ({
    ...currentContact,
    address1: data.address,
    city: data.city,
    zip: data.zip,
    country: country[0],
}));

setContact的引用永远不会改变,它总是会给你当前的联系人对象。(但最好修复SomeComponent


推荐阅读