【问题标题】:How to Add a Value to an Array on Button Press (Having Trouble)如何在按钮按下时向数组添加值(遇到问题)
【发布时间】:2019-04-27 18:23:25
【问题描述】:

我正在设置一个多页表单并将步骤分配给一个数组。

我想弄清楚的是在按下按钮时向表单添加新页面的最佳方式。我的解决方案是构建表单的新页面(不过会有 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>
    )
  }
}

【问题讨论】:

  • 您添加的是字符串而不是对象"{name: 'device 2', component: &lt;StepThree/&gt;},"
  • 我一直在阅读有关对象的内容,但仍然无法弄清楚如何将新行添加到我的步骤数组。
  • 应该是steps: [...previousState.steps, {name: 'device 2', component: &lt;StepThree/&gt;}]

标签: arrays reactjs


【解决方案1】:

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

您正在使用单独的.js 文件来存储步骤。这样,当 steps 数组发生变化时 React 不会收到通知,因此不会更新(它会在某个时候因为其他原因重新渲染,但你通常不希望这样)。

查看react-multistep docs,似乎它们没有提供更新 steps 数组的方法,并且不允许您传递额外的 props 来形成组件。

考虑到您不想引入像 reduxmobx 这样的状态管理库,我看到了两种解决问题的方法:
1.使用React's Context API将状态和更新函数传递给表单组件
2. 创建react-multistep 的分支,使其将传递给MultiStep 组件的道具传递给表单组件——库非常小(基本上只有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>
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 2019-08-23
    • 2021-10-08
    • 2015-03-27
    相关资源
    最近更新 更多