以下是触发操作并监视更改的组件:

import { Box, Button, Stack, TextField, Typography } from "@mui/material";
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { v4 as uuidv4 } from "uuid";
import {
  handleDirectorAdd,
  handleDirectorInfoFormChange,
  handleDirectorRemove,
} from "../../../../redux/slices/directorInfo";

const DirectorsInformation = () => {
  const dispatch = useDispatch();
  const directorsInfo = useSelector((state) => state.directorInfo);

  const handleChange = (e, index) => {
    const { name, value } = e.target;
    if (name && value) {
      dispatch(handleDirectorInfoFormChange({ name, value, index }));
    }
  };

  const handleAdd = () => {
    dispatch(handleDirectorAdd());
  };

  const handleRemove = (e, index) => {
    dispatch(handleDirectorRemove({ index }));
  };

  return (
    <form
      onSubmit={handleSubmit}
      noValidate
      style={{
        padding: "1rem",
        backgroundColor: "white",
        border: "1px solid darkgrey",
        textAlign: "center",
      }}
    >
      <Typography variant="body1">
        <strong>Director&apos;s Information</strong>
      </Typography>
      <hr />
      {directorsInfo?.map((directorInfo, index) => (
        <div key={uuidv4()}>
          <Stack
            spacing={1}
            alignItems="center"
            style={{
              padding: "1rem",
              backgroundColor: "rgb(227, 227, 227)",
            }}
          >
            <Typography variant="body1">Director&apos;s Information</Typography>
            <Button
              variant="contained"
              color="error"
              sx={{ textTransform: "none" }}
              onClick={(e) => handleRemove(e, index)}
            >
              Remove
            </Button>
            <Typography variant="body1">
              <strong>Full Name</strong>
            </Typography>
            <TextField
              fullWidth
              size="small"
              label="Full Name"
              name="name"
              value={directorInfo.name}
              onChange={(e) => handleChange(e, index)}
              sx={{ backgroundColor: "white" }}
            />
            <Typography variant="body1">
              <strong>Official Email</strong>
            </Typography>
            <TextField
              fullWidth
              size="small"
              label="Official Email"
              name="email"
              type="email"
              value={directorInfo.email}
              onChange={(e) => handleChange(e, index)}
              sx={{ backgroundColor: "white" }}
            />
            <Typography variant="body1">
              <strong>Contact Number</strong>
            </Typography>
            <TextField
              fullWidth
              size="small"
              label="Contact Number"
              name="contactNumber"
              value={directorInfo.contactNumber}
              onChange={(e) => handleChange(e, index)}
              sx={{ backgroundColor: "white" }}
            />
            <Typography variant="body1">
              <strong>Title</strong>
            </Typography>
            <TextField
              fullWidth
              size="small"
              label="Tile"
              name="title"
              type="string"
              value={directorInfo.title}
              onChange={(e) => handleChange(e, index)}
              sx={{ backgroundColor: "white" }}
            />
          </Stack>
          <Button
            variant="contained"
            color="success"
            sx={{ textTransform: "none", margin: "2rem 0" }}
            onClick={handleAdd}
          >
            Add Directors Information
          </Button>
        </div>
      ))}
    </form>
  );
};

export default DirectorsInformation;

现在减速器和动作如下所示:

import { createSlice, current } from "@reduxjs/toolkit";
const initialValues = {
  name: "",
  email: "",
  contactNumber: "",
  username: "",
  title: "",
};
const initialState = [initialValues];

const directorInfo = createSlice({
  name: "directorInfo",
  initialState,
  reducers: {
    handleDirectorAdd(state, action) {
      return [...state, initialValues];
    },
    handleDirectorRemove(state, action) {
      return state.filter((_, index) => index !== action.payload.index);
    },
    handleDirectorInfoFormChange(state, action) {
      const { index, name, value } = action.payload;
      return state.map((director, idx) => {
          if (idx === index) {
          return {
            ...director,
            [name]: value,
          };
        } else {
          return director;
        }
      });
    },
  },
});

export const {
  handleDirectorAdd,
  handleDirectorRemove,
  handleDirectorInfoFormChange,
} = directorInfo.actions;

export default directorInfo.reducer;

我面临的问题是,当我更改表单输入字段中的值时,该值会更新,但会导致重新呈现(我假设这是因为移除了对输入字段的关注).当更改任何控制器的值或添加和删除它们时,我正在try 更新REDUX存储中的状态.任何帮助都将不胜感激.

谢谢

我试图改变这个州.这个状态正在正确地变化,但是它导致了重新渲染,这是我不希望的.我已经try 了过滤功能,而不是 map ,但仍然无法达到预期的结果.我希望用户可以在输入框内流畅地书写

推荐答案

Issue

当您更新状态时,预期的结果将是重新生成器.但是,您的根本问题是在映射的directorsInfo状态数组上每个呈现周期使用一个随机的Reaction键引起的.

{directorsInfo?.map((directorInfo, index) => (
  <div key={uuidv4()}> // <-- Random React key == bad
    ...
  </div>
))}

每次重新呈现DirectorsInformation次时,每个映射的directorsInfo数组元素的JSX都使用102 REACTIVE键(than from the previous render cycle),因此REACT将该JSX视为新的,并卸载旧的JSX并挂载新的JSX even though.

Solution

几乎从来不使用随机的react 键.理想情况下,您希望使用与要呈现的数据本质相关的键值,如数据的任何GUID或数据的唯一属性,这些属性在数据的生命周期内与数据一起存在.

在这种情况下,我建议为您的州添加id个属性.如果你愿意,你可以继续使用uuid包,但是Redux-Toolkit也会为这样的用例重新导出nanoid包.

示例:

import { createSlice, nanoid } from "@reduxjs/toolkit";

const initialValues = {
  name: "",
  email: "",
  contactNumber: "",
  username: "",
  title: "",
};

const initialState = [{
  ...initialValues,
  id: nanoid(), // <-- generate id when creating object
}];

const directorInfo = createSlice({
  name: "directorInfo",
  initialState,
  reducers: {
    handleDirectorAdd(state, action) {
      state.push({
        ...initialValues,
        id: nanoid(), // <-- generate id when creating object
      });
    },
    handleDirectorRemove(state, action) {
      return state.filter((director) => director.id !== action.payload.id);
    },
    handleDirectorInfoFormChange(state, action) {
      const { id, name, value } = action.payload;

      return state.map((director) => director.id === id
        ? { ...director, [name]: value }
        : director);
    },
  },
});
const DirectorsInformation = () => {
  const dispatch = useDispatch();
  const directorsInfo = useSelector((state) => state.directorInfo);

  const handleChange = (e, id) => {
    const { name, value } = e.target;
    if (name && value) {
      dispatch(handleDirectorInfoFormChange({ name, value, id }));
    }
  };

  const handleAdd = () => {
    dispatch(handleDirectorAdd());
  };

  const handleRemove = (e, id) => {
    dispatch(handleDirectorRemove({ id }));
  };

  return (
    <form
      onSubmit={handleSubmit}
      noValidate
      style={{
        padding: "1rem",
        backgroundColor: "white",
        border: "1px solid darkgrey",
        textAlign: "center",
      }}
    >
      <Typography variant="body1">
        <strong>Director&apos;s Information</strong>
      </Typography>
      <hr />
      {directorsInfo?.map((director) => (
        <div key={director.id}> // <-- use id property
          <Stack
            spacing={1}
            alignItems="center"
            style={{
              padding: "1rem",
              backgroundColor: "rgb(227, 227, 227)",
            }}
          >
            <Typography variant="body1">Director&apos;s Information</Typography>
            <Button
              variant="contained"
              color="error"
              sx={{ textTransform: "none" }}
              onClick={(e) => handleRemove(e, director.id)} // <-- pass id property
            >
              Remove
            </Button>
            <Typography variant="body1">
              <strong>Full Name</strong>
            </Typography>
            <TextField
              fullWidth
              size="small"
              label="Full Name"
              name="name"
              value={director.name}
              onChange={(e) => handleChange(e, director.id)} // <-- pass id property
              sx={{ backgroundColor: "white" }}
            />
            <Typography variant="body1">
              <strong>Official Email</strong>
            </Typography>
            <TextField
              fullWidth
              size="small"
              label="Official Email"
              name="email"
              type="email"
              value={director.email}
              onChange={(e) => handleChange(e, director.id)} // <-- pass id property
              sx={{ backgroundColor: "white" }}
            />
            <Typography variant="body1">
              <strong>Contact Number</strong>
            </Typography>
            <TextField
              fullWidth
              size="small"
              label="Contact Number"
              name="contactNumber"
              value={director.contactNumber}
              onChange={(e) => handleChange(e, director.id)} // <-- pass id property
              sx={{ backgroundColor: "white" }}
            />
            <Typography variant="body1">
              <strong>Title</strong>
            </Typography>
            <TextField
              fullWidth
              size="small"
              label="Tile"
              name="title"
              type="string"
              value={director.title}
              onChange={(e) => handleChange(e, director.id)} // <-- pass id property
              sx={{ backgroundColor: "white" }}
            />
          </Stack>
          <Button
            variant="contained"
            color="success"
            sx={{ textTransform: "none", margin: "2rem 0" }}
            onClick={handleAdd}
          >
            Add Directors Information
          </Button>
        </div>
      ))}
    </form>
  );
};

Javascript相关问答推荐

JS、C++和C#给出不同的Base 64 Guid编码结果

TypScript界面中的Infer React子props

窗口.getComputedStyle()在MutationObserver中不起作用

React 17与React 18中的不同setState行为

Phaser 3 console. log()特定游戏角色的瓷砖属性

在vercel throws上部署带有gunjs的sveltekit应用无法找到模块./' lib/文本编码'

你怎么看啦啦队的回应?

我可以使用使用node.js创建的本地主机来存储我网站上提交的所有数据吗?没有SQL或任何数据库.只有HTML语言

同一类的所有div';S的模式窗口

如何确保预订系统跨不同时区的日期时间处理一致?

自定义图表工具提示以仅显示Y值

每次重新呈现时调用useState initialValue函数

未捕获语法错误:Hello World中的令牌无效或意外

无法检索与Puppeteer的蒸汽游戏的Bundle 包价格

输入的值的类型脚本array.排序()

有没有办法更改Chart.js 3.x.x中主要刻度的字体?

JavaScript:多个图像错误处理程序

限制数组中每个元素的长度,

验证Java脚本函数中的两个变量

Reaction路由v6.4+数据API:重试加载程序而不显示错误