【问题标题】:Can't add items to material-ui form无法将项目添加到 material-ui 表单
【发布时间】:2020-02-11 21:15:44
【问题描述】:

我从别人那里得到了一个项目,我需要将一些项目添加到使用 react 和 material-ui 创建的表单中。我可以让文本字段正常工作,但如果我尝试添加一个下拉列表,它在选择时不会保留该值。

我遵循相同的惯例,将项目添加到创建此表单的人使用的表单中。

我添加了一个网格项目,其中包含一个表单控件组件。里面还有一个带有“游戏”对象的 defaultprops 设置,它具有所有表单字段作为属性。我还在那里添加了新的字段项。

这是整个表单组件,因为我不确定问题出在哪里。

import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import history from '~/utils/history';
import { FormControl, Button, TextField, Grid, MenuItem, FormHelperText } from '@material-ui/core';
import { DateTimePicker } from 'material-ui-pickers';
import gameState from '~/utils/enums';
import { dateTime } from '~/utils/formats';

import { getById, create, update, remove } from '~/services/games';
import { getAll as getLeagues } from '~/services/leagues';
import { getAll as getSeasons } from '~/services/seasons';
import { getAll as getTeams } from '~/services/teams';

const GameForm = ({ game, id }) => {
  useEffect(() => {
    console.log({ form, game });
  });

  const [edit, setEdit] = useState(false);
  const [form, setForm] = useState(game);
  const [error, setError] = useState('');
  const [variant, setVariant] = useState('outlined');

  const [leagues, setLeagues] = useState([]);
  const [seasons, setSeasons] = useState([]);
  const [teams, setTeams] = useState([]);
  const [gametype, setGametype] = useState(1);

  const gametypes = [
    { key: 0, value: 'Series Game' },
    { key: 1, value: 'Playoff' },
    { key: 2, value: 'Final' },
    { key: 3, value: 'Else' }
  ];

  useEffect(() => {
    getSeasons()
      .then(({ data }) => {
        setSeasons(data);
        return getLeagues();
      })
      .then(({ data }) => {
        setLeagues(data);
        if (id) {
          getById(id).then(({ data }) => setForm(data));
        } else {
          setEdit(true);
        }
      });
  }, []);

  useEffect(() => {
    if (edit) {
      setVariant('outlined');
    } else {
      setVariant('standard');
    }
  }, [edit]);

  useEffect(() => {
    if (form.league) {
      getTeams({ leagues: [form.league] }).then(({ data }) => setTeams(data));
    }
  }, [form.league]);

  useEffect(() => {
    if (form.gametype) {
      setGametype('Playoff');
    }
  }, [form.gametype]);

  const handleChange = ({ target }) => {
    let { name, value } = target;
    setForm({
      ...form,
      [name]: value
    });
  };

  const handleDateChange = formInputName => {
    const dateHandler = moment => {
      setForm({
        ...form,
        [formInputName]: moment ? moment.toDate() : null
      });
    };
    return dateHandler;
  };

  const handleFormSubmit = () => {
    if (!edit) {
      setEdit(true);
    } else {
      new Promise(resolve => {
        resolve(form._id ? update(form) : create(form));
      })
        .then(() => {
          history.push('/games');
        })
        .catch(error => setError(error.response.data.error));
    }
  };
  const handleDelete = () => {
    if (window.confirm(`Delete permanently?`)) {
      remove(id).then(() => history.goBack());
    }
  };

  const handleCancel = () => {
    if (edit && id) {
      setEdit(false);
    } else {
      history.goBack();
    }
  };
  return (
    <Grid container spacing={8} justify="space-between">
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            required
            select
            id="season"
            name="season"
            label="Season"
            variant={variant}
            disabled={!edit}
            value={form.season}
            onChange={handleChange}
          >
            {seasons.map(option => (
              <MenuItem key={option.name} value={option._id}>
                {option.name}
              </MenuItem>
            ))}
          </TextField>
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            required
            select
            id="league"
            name="league"
            label="League"
            variant={variant}
            disabled={!edit}
            value={form.league}
            onChange={handleChange}
          >
            {leagues.map(option => (
              <MenuItem key={option.name} value={option._id}>
                {option.name}
              </MenuItem>
            ))}
          </TextField>
        </FormControl>
      </Grid>
      <Grid item xs={12}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <DateTimePicker
            required
            id="start"
            name="start"
            label="Game starts"
            variant={variant}
            disabled={!edit || !form.season}
            autoOk
            ampm={false}
            keyboard
            clearable
            minDate={form.season ? seasons.find(({ _id }) => _id === form.season).start : undefined}
            minDateMessage="Cannot start before the season begins"
            maxDate={form.season ? seasons.find(({ _id }) => _id === form.season).end : undefined}
            maxDateMessage="Cannot start after the end of the season"
            value={form.start}
            onChange={handleDateChange('start')}
            {...dateTime}
          />
          <FormHelperText disabled={!form.season}>
            {!form.season ? 'Select season first' : undefined}
          </FormHelperText>
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            required
            select
            id="home"
            name="home"
            label="Home team"
            variant={variant}
            disabled={!edit || !form.league}
            helperText={!form.league ? 'Select league first' : undefined}
            value={form.home}
            onChange={handleChange}
          >
            <MenuItem value="">
              <em>None</em>
            </MenuItem>
            {teams
              .filter(({ _id }) => _id !== form.away)
              .map(option => (
                <MenuItem key={option.name} value={option._id}>
                  {option.name}
                </MenuItem>
              ))}
          </TextField>
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            required
            select
            id="away"
            name="away"
            label="Team away"
            variant={variant}
            disabled={!edit || !form.league}
            helperText={!form.league ? 'Select league first' : undefined}
            value={form.away}
            onChange={handleChange}
          >
            <MenuItem value="">
              <em>None</em>
            </MenuItem>
            {teams
              .filter(({ _id }) => _id !== form.home)
              .map(option => (
                <MenuItem key={option.name} value={option._id}>
                  {option.name}
                </MenuItem>
              ))}
          </TextField>
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            required
            select
            id="gametype"
            label=" Game type"
            variant={variant}
            disabled={!edit}
            value={form.gametype}
            onChange={handleChange}
          >
            <MenuItem value="">
              <em>None</em>
            </MenuItem>
            {gametypes.map(option => (
              <MenuItem key={option.key} value={option.value}>
                {option.value}
              </MenuItem>
            ))}
          </TextField>
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            text
            id="umpire"
            label="Umpire"
            variant={variant}
            disabled={!edit || !form.league}
          />
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            text
            id="scorekeeper"
            label="Scorekeeper"
            variant={variant}
            disabled={!edit || !form.league}
          />
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            text
            id="referee1"
            label="Referee 1"
            variant={variant}
            disabled={!edit || !form.league}
          />
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            text
            id="referee2"
            label="Referee 2"
            variant={variant}
            disabled={!edit || !form.league}
          />
        </FormControl>
      </Grid>
      <Grid item xs={12} md={6}>
        <FormControl margin="normal" required fullWidth variant="outlined">
          <TextField
            text
            id="referee3"
            label="Referee 3"
            variant={variant}
            disabled={!edit || !form.league}
          />
        </FormControl>
      </Grid>
      <Grid item xs={edit && id ? 4 : 6}>
        <Button variant="outlined" color="secondary" fullWidth onClick={handleCancel}>
          {edit && id ? 'Cancel' : 'Back'}
        </Button>
      </Grid>
      {edit && id ? (
        <Grid item xs={4}>
          <Button
            type="submit"
            variant="contained"
            color="secondary"
            fullWidth
            onClick={handleDelete}
          >
            Delete
          </Button>
        </Grid>
      ) : null}
      <Grid item xs={edit && id ? 4 : 6}>
        <Button
          type="submit"
          variant="outlined"
          color="primary"
          fullWidth
          onClick={handleFormSubmit}
        >
          {edit ? (id ? 'Save' : 'Create') : 'Edit Game'}
        </Button>
      </Grid>
      {!edit ? (
        <Grid item xs={12}>
          <Button
            variant="outlined"
            color="primary"
            fullWidth
            onClick={() => {
              history.push('/games/' + id + '/scores');
            }}
          >
            EDIT SCORES
          </Button>
        </Grid>
      ) : null}
    </Grid>
  );
};

GameForm.defaultProps = {
  game: {
    season: '',
    league: '',
    start: null,
    home: '',
    away: '',
    gametype: '',
    umpire: '',
    scorekeeper: '',
    referee1: '',
    referee2: '',
    referee3: ''
  }
};

GameForm.propTypes = {
  //classes: PropTypes.object.isRequired,
  game: PropTypes.object
};

export default GameForm;

我注意到,如果我将游戏对象打印到控制台,它只会显示旧表单项,而不是我添加的新表单项。新项目是:比赛类型、裁判员、记分员、裁判员1-3。

我已经尝试了几天来完成这项工作,因此非常感谢任何帮助。

【问题讨论】:

  • 你需要 onChange={handleChange} 在那些 并且你还需要提供名称作为道具
  • 哦,我忘记了新文本字段中的 onChange,但游戏类型下拉列表中有 onChange={handleChange} 并且它不起作用。如果我选择一个项目,它不会粘住。
  • 正如我上面提到的,您的 handleChange 需要 { name } 作为道具,以便它可以使用动态属性来更新状态。
  • 好吧,这更有意义,因为 handleChange 被定义为 handleChange({ target})。但例如季节下拉菜单有效,它只有 onChange={handleChange}。 prop 是如何传递给那里的 handleChange 的?
  • onChange 将传递事件接口----“事件接口的目标属性是对调度事件的对象的引用。”developer.mozilla.org/en-US/docs/Web/API/Event/target

标签: reactjs forms material-ui


【解决方案1】:

你需要 onChange={handleChange} 并且你还需要提供名称作为道具

顺便说一句,我强烈建议您将这些 useState 组合为一个状态对象

例如,一个替代方案禁止在一个组件中调用多个 useState()。你会将状态保存在一个对象中。

function Form() {
  const [state, setState] = useState({
    edit: '',
    form: '',
    error: '',
  });
  // ...
}

需要明确的是,Hooks 确实允许这种风格。您不必将状态拆分为一堆状态变量(请参阅doc)。

【讨论】:

    猜你喜欢
    • 2018-05-18
    • 1970-01-01
    • 2021-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多