【问题标题】:Material-UI and Redux-form, re renders options clicked on select, how to prevent it?Material-UI 和 Redux-form,点击 select 时重新渲染选项,如何防止?
【发布时间】:2025-12-16 13:25:01
【问题描述】:

所以我的问题是我正在动态呈现选项,当我单击选择或选项时,组件会重新呈现并更改选项,因此我需要单击两次才能在选择中选择一个选项。它正在重新渲染,因为它会重新运行该函数,我是否应该将值 true/false 存储在反应钩子中并在第一次运行时更改它以便它不会重新运行该函数?

这是我的代码

这是创建选项的函数 渲染选项函数

const renderOptions = () => {
    const days = [];
    function dateWithMonthsDelay(months) {
      const date = new Date();
      date.setDate(date.getDate() + months);
      return date;
    }
    let i = 0;
    for (let d = new Date(); d <= dateWithMonthsDelay(7); d.setDate(d.getDate() + 1)) {
      if (isAuthenticated && user) {
        const u = user.name.match(/\d/g);
        if (u) {
          const us = user.name.match(/\d/g).join('');
          if (new Date(d).getDay() === 1
          && (us === '25'
          || us === '26'
          || us === '27'
          || us === '3')) {
            days.push(new Date(d));
          } else if (new Date(d).getDay() === 3 && (
            us === '24'
          || us === '28'
          || us === '22'
          || us === '8'
          || us === '9'
          || us === '14'
          )) {
            days.push(new Date(d));
          } else if ((new Date(d).getDay() === 2 || new Date(d).getDay() === 5) && (
            us === '17'
          || us === '21'
          || us === '7'
          || us === '2'
          || us === '4'
          || us === '18'
          || us === '20'
          || us === '23'
          || us === '10'
          || us === '12'
          || us === '16'
          || us === '5'
          || us === '29'
          || us === '30'
          || us === '11'
          || us === '19'
          )) {
            days.push(new Date(d));
          }
        }
      }
    }
    return days.map((d) => (
      <>
        {i === 0 ? (<option aria-label="None" value="" />) : null}
        {i += 1}
        <option value={d}>
          {moment(d).format('dddd - Do MMMM YYYY')}
        </option>
      </>
    ));
  };

这是表单组件的返回

<Header>
      <Container component="main" maxWidth="md">
        <div className={classes.paper}>
          <Typography component="h1" variant="h5">
            GOLD
          </Typography>
          <form className={classes.form} onSubmit={handleSubmit(onSubmit)} noValidate>
            <Field name="twentytwo" id="twentytwo" type="number" label="22k" component={renderField} />
            <Field name="eighteen" id="eighteen" type="number" label="18k" autoFocus component={renderField} />
            <Field name="fourteen" id="fourteen" type="number" label="14k" component={renderField} />
            <Field name="nine" id="nine" type="number" label="9k" component={renderField} />
            <Field name="argent" id="argent" type="number" label="Argent" component={renderField} />
            <Field
              name="tournee"
              options={(
                <>
                  {renderOptions}
                </>
            )}
              id="tournee"
              label="Dans la Tournee de"
              component={renderSelect}
            />
            <Button
              type="submit"
              fullWidth
              variant="contained"
              color="secondary"
              className={classes.submit}
            >
              Ajouter
            </Button>
          </form>
        </div>
        <Box mt={8}>
          <Copyright />
        </Box>
      </Container>
    </Header>

这是我的 redux-form 材质 ui 组件 渲染选择

export const renderSelect = ({
  input, label, meta, id, className, fullWidth, options,
}) => (
  <>
    <FormControl fullWidth error={meta.touched && meta.error} variant="outlined" className={className} required>
      <InputLabel htmlFor={id}>{label}</InputLabel>
      <Select native {...input} id={id} label={label}>
        {options}
      </Select>
      {renderFromHelper(meta.touched, meta.error)}
    </FormControl>
  </>
);

【问题讨论】:

    标签: javascript reactjs redux material-ui redux-form


    【解决方案1】:

    所以我通过向状态添加选项来解决它,这里的运行状态是代码

    const GoldForm = ({
      change, handleSubmit, weight, addGold, onSubmit, user, isAuthenticated,
    }) => {
      const classes = useStyles();
      const [options, setOptions] = React.useState(null);
      const [run, setRun] = React.useState(true);
      useEffect(() => {
        renderOptions();
      }, [user]);
    
      const renderOptions = () => {
        if (run) {
          const days = [];
          function dateWithMonthsDelay(months) {
            const date = new Date();
            date.setDate(date.getDate() + months);
            return date;
          }
          let i = 0;
          for (let d = new Date(); d <= dateWithMonthsDelay(7); d.setDate(d.getDate() + 1)) {
            if (isAuthenticated && user) {
              const u = user.name.match(/\d/g);
              if (u) {
                const us = user.name.match(/\d/g).join('');
                if (new Date(d).getDay() === 1
                && (us === '25'
                || us === '26'
                || us === '27'
                || us === '3')) {
                  days.push(new Date(d));
                } else if (new Date(d).getDay() === 3 && (
                  us === '24'
                || us === '28'
                || us === '22'
                || us === '8'
                || us === '9'
                || us === '14'
                )) {
                  days.push(new Date(d));
                } else if ((new Date(d).getDay() === 2 || new Date(d).getDay() === 5) && (
                  us === '17'
                || us === '21'
                || us === '7'
                || us === '2'
                || us === '4'
                || us === '18'
                || us === '20'
                || us === '23'
                || us === '10'
                || us === '12'
                || us === '16'
                || us === '5'
                || us === '29'
                || us === '30'
                || us === '11'
                || us === '19'
                )) {
                  days.push(new Date(d));
                }
              }
            }
          }
          const a = days.map((d, index) => (
            <React.Fragment key={index + 1}>
              {i === 0 ? (<option aria-label="None" value="" />) : null}
              {i += 1}
              <option value={d}>
                {moment(d).format('dddd - Do MMMM YYYY')}
              </option>
            </React.Fragment>
          ));
          setOptions(a);
          setRun(false);
        }
      };
    
      return (
        <Header>
          <Container component="main" maxWidth="md">
            <div className={classes.paper}>
              <Typography component="h1" variant="h5">
                GOLD
              </Typography>
              <form className={classes.form} onSubmit={handleSubmit(onSubmit)} noValidate>
                <Field name="twentytwo" id="twentytwo" type="number" label="22k" component={renderField} />
                <Field name="eighteen" id="eighteen" type="number" label="18k" autoFocus component={renderField} />
                <Field name="fourteen" id="fourteen" type="number" label="14k" component={renderField} />
                <Field name="nine" id="nine" type="number" label="9k" component={renderField} />
                <Field name="argent" id="argent" type="number" label="Argent" component={renderField} />
                <Field
                  name="tournee"
                  options={options}
                  id="tournee"
                  label="Dans la Tournee de"
                  component={renderSelect}
                />
                <Button
                  type="submit"
                  fullWidth
                  variant="contained"
                  color="secondary"
                  className={classes.submit}
                >
                  Ajouter
                </Button>
              </form>
            </div>
            <Box mt={8}>
              <Copyright />
            </Box>
          </Container>
        </Header>
      );
    };
    

    【讨论】: