如何在按钮按下时将值添加到数组(有问题)

时间:2019-04-27 18:23:25

标签: arrays reactjs

我正在建立一个多页表单,并将步骤分配给数组。

我要弄清楚的是在按钮按下时向表单添加新页面的最佳方法。我的解决方案是构建表单的新页面(尽管会有20个重复项,每个重复项都有自己的变量)。

然后,我有一个标记为“添加新”的按钮,该按钮调用一个函数来向阵列添加新行,从而启用下一页。

当然,理想情况下,我的第一个解决方案是让react自动构建新页面和变量,但是我不确定这样做是否可行。

steps.js:

import React from 'react'
import { StepOne } from './StepOne'
import { StepTwo } from './StepTwo'
import { StepThree } from './StepThree'



const steps = 
    [
      {name: 'Job', component: <StepOne/>},
      {name: 'device 1', component: <StepTwo/>},

    ]

export { steps }

home.js(我的表单所在的位置)

import React, { Component } from "react";
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import MultiStep from 'react-multistep'
import { steps } from './steps'
import {
  Route,
  NavLink,
  HashRouter
} from "react-router-dom";
import newdevice from "./new-device";


class Home extends Component {
  render() {
    return (
        <div>
        <h1>Start a New Job</h1>

        <div className='container'>
    <div>
      <MultiStep steps={steps} />
    </div>
    <div className='container app-footer'>
      <h6>Press 'Enter' or click on progress bar for next step.</h6>
    </div>
</div>
        </div>

    );
  }
}

export default Home;

StepTwo.js

import React from 'react'
import { steps } from './steps'
import { StepThree } from './StepThree'
import update from 'react-addons-update';


export class StepTwo extends React.Component {

    addNew() {
      this.setState(previousState => ({
        steps: [...previousState.steps, "{name: 'device 2', component: <StepThree/>},"]
      }));
  }
        <div className='row'> 
        <div className="col-md-4">
        <button  onClick={this.addNew} variant="primary">Add a New Device</button>
        </div>
        </div>
      </div>
    )
  }
}

如果您想查看表单的整个页面以获得更好的主意,请完整填写StepTwo.js

import React from 'react'
import { steps } from './steps'
import { StepThree } from './StepThree'
import update from 'react-addons-update'; // ES6
// 


export class StepTwo extends React.Component {

    addNew() {
      this.setState(previousState => ({
        steps: [...previousState.steps, "{name: 'device 2', component: <StepThree/>},"]
      }));
  }



  constructor () {
    super()
    this.state = { 
      Box: '', 
      VIN: '',
      Lbl: '',
      Year: '',
      Make: '',
      Model: '',
      Plate: '',
      ODO: '',
      Notes: '',
    }
    this.handleBoxChanged = this.handleBoxChanged.bind(this);
    this.handleVINChanged = this.handleVINChanged.bind(this);
    this.handleLblChanged = this.handleLblChanged.bind(this);
    this.handleYearhanged = this.handleYearChanged.bind(this);
    this.handleMakeChanged = this.handleMakeChanged.bind(this);
    this.handleModelChanged = this.handleModelChanged.bind(this);
    this.handlePlateChanged = this.handlePlateChanged.bind(this);
    this.handleODOChanged = this.handleODOChanged.bind(this);
    this.handleNotesChanged = this.handleNotesChanged.bind(this);
  }

  handleBoxChanged (event) {
    this.setState({Box: event.target.value})
  }
  handleVINChanged (event) {
    this.setState({VIN: event.target.value})
  }

  handleLblChanged (event) {
    this.setState({Lbl: event.target.value})
  }

  handleYearChanged (event) {
    this.setState({Year: event.target.value})
  }

  handleMakeChanged (event) {
    this.setState({Make: event.target.value})
  }

  handleModelChanged (event) {
    this.setState({Model: event.target.value})
  }

  handlePlateChanged (event) {
    this.setState({Plate: event.target.value})
  }

  handleODOChanged (event) {
    this.setState({ODO: event.target.value})
  }

  handleNotesChanged (event) {
    this.setState({Notes: event.target.value})
  }


  render () {
    return (
      <div>
        <div className='row'>
          <div className='six columns'>
            <label>Device #</label>
            <input
              className='u-full-width'
              placeholder='Device #'
              type='text'
              onChange={this.handleBoxChanged}
              value={this.state.Box}
              autoFocus
            />
          </div>
        </div>
        <div className='row'>
          <div className='six columns'>
            <label>VIN</label>
            <input
              className='u-full-width'
              placeholder='VIN'
              type='text'
              onChange={this.handleVINChanged}
              value={this.state.VIN}
            />
          </div>
        </div>
        <div className='row'>
          <div className='six columns'>
            <label>Label</label>
            <input
              className='u-full-width'
              placeholder='Label'
              type='text'
              onChange={this.handleLblChanged}
              value={this.state.Lbl}
            />
          </div>
        </div>
        <div className='row'>
          <div className='six columns'>
            <label>Year</label>
            <input
              className='u-full-width'
              placeholder='Year'
              type='text'
              onChange={this.handleYearChanged}
              value={this.state.Year}
            />
          </div>
        </div>
        <div className='row'>
          <div className='six columns'>
            <label>Make</label>
            <input
              className='u-full-width'
              placeholder='Make'
              type='text'
              onChange={this.handleMakeChanged}
              value={this.state.Make}
            />
          </div>
        </div>
        <div className='row'>
          <div className='six columns'>
            <label>Model</label>
            <input
              className='u-full-width'
              placeholder='Model'
              type='text'
              onChange={this.handleModelChanged}
              value={this.state.Model}
            />
          </div>
        </div>
        <div className='row'>
          <div className='six columns'>
            <label>Plate</label>
            <input
              className='u-full-width'
              placeholder='VPlateIN'
              type='text'
              onChange={this.handlePlateChanged}
              value={this.state.Plate}
            />
          </div>
        </div>
        <div className='row'>
          <div className='six columns'>
            <label>ODO</label>
            <input
              className='u-full-width'
              placeholder='ODO'
              type='text'
              onChange={this.handleODOChanged}
              value={this.state.ODO}
            />
          </div>
        </div>
        <div className='row'>
          <div className='six columns'>
            <label>Notes</label>
            <input
              className='u-full-width'
              placeholder='Notes'
              type='text'
              onChange={this.handleNotesChanged}
              value={this.state.VIN}
            />
          </div>
        </div>
        <div className='row'> 
        <div className="col-md-4">
        <button  onClick={this.addNew} variant="primary">Add a New Device</button>
        </div>
        </div>
      </div>
    )
  }
}

1 个答案:

答案 0 :(得分:0)

主要问题是您试图在setState组件内调用StepTwo,但是没有将步骤存储为组件状态。

您正在使用单独的.js文件来存储步骤。这样,当steps数组更改时,React不会得到通知,因此不会更新(有时会因为其他原因而重新渲染它,但通常不希望这样做)。

react-multistep文档,似乎它们没有提供更新步骤数组的方法,也不允许您传递其他道具来形成组件。

考虑到您不想引入诸如reduxmobx之类的状态管理库,我为您解决此问题提供了两种方法:
1.使用React's Context API将状态和更新功能传递给表单组件
2.创建一个react-multistep的fork,以使其将传递给MultiStep组件的props传递到表单组件-库很小(基本上只有1个小组件)。这样,您将能够使用组件的状态。

使用Context API的解决方案:

import React, { Component } from "react";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import MultiStep from "react-multistep";
import { Route, NavLink, HashRouter } from "react-router-dom";
import newdevice from "./new-device";

export const StepsContext = React.createContext();

class Home extends Component {
  state = {
    steps: [
      { name: "Job", component: <StepOne /> },
      { name: "device 1", component: <StepTwo /> }
    ]
  };

  addStep = newStep => {
    this.setState(prevState => ({
      steps: [...prevState.steps, newStep]
    }));
  };

  render() {
    const { steps } = this.state;

    return (
      <StepsContext.Provider value={{ steps, addStep: this.addStep }}>
        <div>
          <h1>Start a New Job</h1>

          <div className="container">
            <div>
              <MultiStep steps={steps} />
            </div>
            <div className="container app-footer">
              <h6>Press 'Enter' or click on progress bar for next step.</h6>
            </div>
          </div>
        </div>
      </StepsContext.Provider>
    );
  }
}

export default Home;

然后,在表单组件中:

import { StepsContext } from "./Home";

const AddStepComponent = () => (
  <StepsContext.Consumer>
    {({ addStep }) => (
      <button
        onClick={() => addStep({ name: "device 2", component: <StepThree /> })}
      >
        Add a new step
      </button>
    )}
  </StepsContext.Consumer>
);