我正在建立一个多页表单,并将步骤分配给数组。
我要弄清楚的是在按钮按下时向表单添加新页面的最佳方法。我的解决方案是构建表单的新页面(尽管会有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>
)
}
}
答案 0 :(得分:0)
主要问题是您试图在setState
组件内调用StepTwo
,但是没有将步骤存储为组件状态。
您正在使用单独的.js
文件来存储步骤。这样,当steps数组更改时,React不会得到通知,因此不会更新(有时会因为其他原因而重新渲染它,但通常不希望这样做)。
看react-multistep
文档,似乎它们没有提供更新步骤数组的方法,也不允许您传递其他道具来形成组件。
考虑到您不想引入诸如redux
或mobx
之类的状态管理库,我为您解决此问题提供了两种方法:
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>
);