首页 > 解决方案 > 更改输入值后,表 1 的值需要保持不变

问题描述

我是 React 的新手,我试图通过单击按钮添加表格行。问题是输入标签中的值被添加到表中。但是在添加另一行时值需要保持不变。一旦我更改输入中的值,相应的表行值也会更改。我希望表值是永久的并且根据输入标签中的输入变化而有所不同。

这是我的 KPI 详细信息代码:

export class KPIDetails extends Component {
  state = {
    rows: [],
    idx: [1]
  };
  continue = e => {
    e.preventDefault();
    this.props.nextStep();
  };

  handleChangeRows = idx => e => {
    const { name, value } = e.target;
    const rows = [...this.state.rows];
    rows[idx] = {
      [name]: value
    };
    this.setState({
      rows
    });
  };

  //2
  handleAddRow = () => {
    const item = {
      KPI_Before: "",
      UOM_Before: "",
      Base_Before: "",
      Target_Before: "",
      dateTime: ""
    };
    this.setState({
      rows: [...this.state.rows, item]
    });
  };

  //3
  handleRemoveRow = () => {
    this.setState({
      rows: this.state.rows.slice(0, -1)
    });
  };
  setDate = dateTime => this.setState({ dateTime });

  render() {
    const { values, handleChange } = this.props;
    const {
      values: {
        Title,
        Details,
        What,
        Why,
        How,
        Status,
        Cost,
        Benefits,
        Kpi_Before,
        Kpi_After,
        UOM_Before,
        Base_Before,
        Target_Before,
        Time,
        dateTime
      }
    } = this.props;
    return (
      <MuiThemeProvider theme={theme}>
        <React.Fragment>
          <div className={useStyles.root}>
            <AppBar position="static">
              <Toolbar>
                <Typography
                  gutterBottom
                  align="center"
                  style={{ width: "100%", alignItems: "center" }}
                >
                  KPI Before Implementation
                </Typography>
              </Toolbar>
            </AppBar>
          </div>
          <br />
          <br />
          <Grid container>
            <Grid item xs={6}>
              <TextField
                label="KPI"
                id="Kpi_Before"
                variant="outlined"
                size="small"
                placeholder="Enter the KPI"
                onChange={handleChange("Kpi_Before")}
                defaultValue={values.Kpi_Before}
                style={{ width: "80%" }}
              />
            </Grid>
            <Grid item xs={6}>
              <FormControl style={{ width: "80%" }} size="small">
                <InputLabel
                  htmlFor="UOM_Before"
                  style={{
                    marginLeft: 10,
                    top: "50%",
                    transform: "translate(0,-50%"
                  }}
                >
                  UOM
                </InputLabel>
                <Select
                  labelId="UOM_Before"
                  name="name"
                  onChange={handleChange("UOM_Before")}
                  defaultValue={values.UOM_Before}
                  variant="outlined"
                  inputProps={{
                    id: "UOM_Before"
                  }}
                >
                  <MenuItem value="Nos">Nos</MenuItem>
                  <MenuItem value="Percentage">Percentage</MenuItem>
                  <MenuItem value="Metric">Metric</MenuItem>
                </Select>
              </FormControl>
            </Grid>
          </Grid>
          <br />
          <br />
          <br />
          <br />
          <Grid container>
            <Grid item xs={6}>
              <TextField
                label="Base Level"
                variant="outlined"
                size="small"
                placeholder="Enter the Base Level"
                onChange={handleChange("Base_Before")}
                style={{ width: "80%" }}
              />
            </Grid>
            <Grid item xs={6}>
              <TextField
                label="Target Level"
                variant="outlined"
                size="small"
                placeholder="Enter the Target Level"
                onChange={handleChange("Target_Before")}
                defaultValue={values.Target_Before}
                style={{ width: "80%" }}
              />
            </Grid>
          </Grid>
          <br />
          <br />
          <br />
          <br />
          <Grid container>
            <Grid item xs={6} direction="row" alignItems="center">
              <TextField
                id="date"
                label="Target Date"
                type="date"
                variant="outlined"
                size="small"
                defaultValue="2017-05-24"
                onChange={handleChange("dateTime")}
                style={{ width: "67%" }}
                InputLabelProps={{
                  shrink: true
                }}
              />

              <Button
                variant="outlined"
                color="primary"
                onClick={this.handleAddRow}
                size="small"
                style={styles.button}
              >
                +
              </Button>
            </Grid>

            <Grid item xs={6}>
              ...
            </Grid>
          </Grid>
          <Grid container>
            <Grid item xs={6} direction="row" alignItems="center">
              <table
                className="table table-bordered table-hover"
                id="tab_logic"
              >
                <thead>
                  <tr>
                    <th className="text-center"> # </th>
                    <th className="text-center"> KPI </th>
                    <th className="text-center"> UOM </th>
                    <th className="text-center"> Base </th>
                    <th className="text-center"> Target </th>
                    <th className="text-center"> Target Date </th>
                  </tr>
                </thead>
                <tbody>
                  {this.state.rows.map((item, idx) => (
                    <tr id="addr1" key={idx}>
                      <td>{idx}</td>
                      <td>
                        <input
                          type="text"
                          name="Kpi_Before"
                          value={Kpi_Before}
                          onChange={this.handleChangeRows(idx)}
                          className="form-control"
                        />
                      </td>
                      <td>
                        <input
                          type="text"
                          name="UOM_Before"
                          value={UOM_Before}
                          onChange={this.handleChangeRows(idx)}
                          className="form-control"
                        />
                      </td>
                      <td>
                        <input
                          type="text"
                          name="Base_Before"
                          value={Base_Before}
                          onChange={this.handleChangeRows(idx)}
                          className="form-control"
                        />
                      </td>
                      <td>
                        <input
                          type="text"
                          name="Target_Before"
                          value={Target_Before}
                          onChange={this.handleChangeRows(idx)}
                          className="form-control"
                        />
                      </td>
                      <td>
                        <input
                          type="text"
                          name="Target_Before"
                          value={dateTime}
                          onChange={this.handleChangeRows(idx)}
                          className="form-control"
                        />
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
              <button
                onClick={this.handleRemoveRow}
                className="pull-right btn btn-default"
              >
                Delete Row
              </button>
            </Grid>
          </Grid>
        </React.Fragment>
      </MuiThemeProvider>
    );
  }
}

const theme = createMuiTheme({
  palette: {
    primary: blue,
    secondary: purple
  },
  status: {
    danger: "orange"
  }
});

const styles = {
  button: {
    margin: 5,
    verticalAlign: "bottom"
  }
};

export default KPIDetails;

这是我的用户表单代码:

export class UserForm extends Component {

  state = {
    step: 1,
    Title: "",
    Details: "",
    What: "",
    Why: "",
    How: "",
    Status: "",
    Cost: "",
    Benefits: "",
    Kpi_Before: "",
    Kpi_After: "",
    Time: "",
    UOM_Before: "",
    Base_Before: "",
    Target_Before: "",
    dateTime: null,
    rows: []
  };

  //1
  handleChangeRows = idx => e => {
    const { Kpi_Before, value } = e.target;
    const rows = [...this.state.rows];
    rows[idx] = {
      [Kpi_Before]: value
    };
    this.setState({
      rows
    });
  };

  //2
  handleAddRow = () => {
    const item = {
      KPI_Before: "",
      UOM_Before: "",
      Base_Before: "",
      Target_Before: "",
      dateTime: ""
    };
    this.setState({
      rows: [...this.state.rows, item]
    });
  };

  //3
  handleRemoveRow = () => {
    this.setState({
      rows: this.state.rows.slice(0, -1)
    });
  };

  //Proceed to next step
  nextStep = () => {
    const { step } = this.state;
    this.setState({
      step: step + 1
    });
  };

  //Go back to previous step
  prevStep = () => {
    const { step } = this.state;
    this.setState({
      step: step - 1
    });
  };

  //Handle fields change
  handleChange = input => e => {
    this.setState({ [input]: e.target.value });
  };

  render() {
    const { step } = this.state;
    const {
      Title,
      Details,
      What,
      Why,
      How,
      Status,
      Cost,
      Benefits,
      Kpi_Before,
      Kpi_After,
      Time,
      UOM_Before,
      Base_Before,
      Target_Before,
      dateTime,
      rows
    } = this.state;

    const values = {
      Title,
      Details,
      What,
      Why,
      How,
      Status,
      Cost,
      Benefits,
      Kpi_Before,
      Kpi_After,
      Time,
      UOM_Before,
      Base_Before,
      Target_Before,
      dateTime,
      rows
    };
    switch (step) {
      case 1:
        return (
          <FormUserDetails
            nextStep={this.nextStep}
            handleChange={this.handleChange}
            values={values}
          />
        );
      case 2:
        return (
          <KPIDetails
            handleChange={this.handleChange}
            values={values}
            nextStep={this.nextStep}
            handleChangeRows={this.handleChangeRows}
            handleAddRow={this.handleAddRow}
            handleRemoveRow={this.handleRemoveRow}
          />
        );

      case 3:
        return (
          <Confirm
            nextStep={this.nextStep}
            prevStep={this.prevStep}
            values={values}
          />
        );
      case 4:
        return <Success />;
    }
  }
}

export default UserForm;

请告诉我如何实现这一目标?

标签: reactjsreact-reduxrxjsmaterial-ui

解决方案


我是新手,所以我对这些概念并不完全清楚。

使用 JavaScript/jQuery 从其输入元素中获取值的传统 HTML 表单是具有不受控制组件的典型表单。没有显式使用状态变量,也没有实现任何事件处理程序来更新输入值。因此,在这种情况下,将 onChange() 插入不受控制的组件将是不必要的。它们的值就是我们输入的内容。在 react 提交表单时,通过附加 ref 的 current 属性实现对元素的引用。因此,用户输入的值可以通过 current.value 获得。

在 React 渲染的生命周期中,表单元素中的值属性会覆盖 DOM 中的值。为了处理这种情况,React 提出了 defaultValue 属性,它指定了初始值,但不控制随后的更新。

React 将输入视为受控(与 prop/state 绑定的值)或不受控(不绑定值)。

当我像这样在表单中使用值时:

                    <td>
                    <input
                      type="text"
                      name="Base_Before"
                      value={Base_Before}
                      onChange={this.handleChangeRows(idx)}
                      className="form-control"
                    />
                  </td>

它的值会在更改输入字段时自动更改。所以每次我更新并向表中添加行时,它的值总是会反映输入字段中的值。Defaultvalue 不会在更新输入值时更新状态,因此在一行中输入的值将保持永久不变,并且不会随着输入字段中的更改而更改。

再次,我是新来的反应,这是我所理解的,如果我错了,请纠正我,希望这会有所帮助


推荐阅读