React Context初始状态正在变异–JavaScript / React
作者:互联网
我正在制作一个指导我部分.本指南的部分内容 – 显示一系列流程.每个进程内都有一个步骤数组,每个步骤中都有一个选项数组.用户从其中一个步骤中选择一个选项,将它们带到下一个相关步骤.如果用户在步骤2中选择了该选项,则可以将它们带到步骤3或返回步骤1.这取决于id.
尽管如此,我的过程中有一些问题在改变我.我正在使用React Context作为全局状态.当用户选择一个选项时,我抓住那个id,然后按该id过滤指定的对象.所以我只能留下具有该特定步骤的流程.发生的事情是我最初的全球状态正以某种方式发生变异.我在这里错过了一些东西,因为我是React的新手.
P.s – 我此刻没有使用任何服务,所以我只是将一些JSON复制到context.js中的初始状态
context.js
import React, { Component } from 'react'
// import axios from 'axios'
const Context = React.createContext()
const reducer = (state, action) => {
switch(action.type){
case 'SEARCH_PROCESS':
return {
...state,
guides: action.payload
}
default:
return state
}
}
export class Provider extends Component {
state = {
guides: [
{
"processName": "Support Messaging",
"steps": [{
"id": "15869594739302",
"title": "step one",
"options": [{
"nextStep": "4767fn-47587n-2819am-9585j,04956840987",
"text": "Option 1 text",
"type": "option"
},
{
"nextStep": "4767fn-47587n-2819am-9585j,04956840987",
"text": "Option 2 text",
"type": "option"
},
{
"nextStep": "",
"text": "Option 3 text",
"type": "option"
}
]
},
{
"id": "04956840987",
"title": "step two",
"options": [{
"nextStep": "4767fn-47587n-2819am-9585j,15869594739302",
"text": "Return to step1",
"type": "option"
},
{
"nextStep": "",
"text": "Option 2 text",
"type": "option"
},
{
"nextStep": "",
"text": "Option 3 text",
"type": "option"
}
]
}
],
"owner": "bob",
"id": "4767fn-47587n-2819am-9585j",
"lastUpdated": 154222227099000,
"tags": ["Tag1", "Tag2", "Tag3"]
}
],
"owner": "bob",
"id": "4767fn-47587n-2819am-9585x",
"lastUpdated": 154222227099000,
"tags": ["Tag1", "Tag2", "Tag3"]
}
],
initialGuide: [
{
"processName": "Support Messaging",
"steps": [{
"id": "15869594739302",
"title": "step one",
"options": [{
"nextStep": "4767fn-47587n-2819am-9585j,04956840987",
"text": "Option 1 text",
"type": "option"
},
{
"nextStep": "4767fn-47587n-2819am-9585j,04956840987",
"text": "Option 2 text",
"type": "option"
},
{
"nextStep": "",
"text": "Option 3 text",
"type": "option"
}
]
},
{
"id": "04956840987",
"title": "step two",
"options": [{
"nextStep": "4767fn-47587n-2819am-9585j,15869594739302",
"text": "Return to step1",
"type": "option"
},
{
"nextStep": "",
"text": "Option 2 text",
"type": "option"
},
{
"nextStep": "",
"text": "Option 3 text",
"type": "option"
}
]
}
],
"owner": "bob",
"id": "4767fn-47587n-2819am-9585j",
"lastUpdated": 154222227099000,
"tags": ["Tag1", "Tag2", "Tag3"]
}
],
dispatch: action => this.setState(state => reducer(state, action))
}
render() {
return (
<Context.Provider value={this.state}>
{this.props.children}
</Context.Provider>
)
}
}
export const Consumer = Context.Consumer;
Guides.js
import React, { Component } from 'react'
import { Consumer } from '../../context'
import Process from './Process'
class Guides extends Component {
constructor (props) {
super(props)
this.state = {
contextValue: [],
searchData: props.location.data
}
}
render () {
console.log(this.props.location.data, this.state, 'logging state and props on guides')
// this.state.searchData = this.props.location.data
return (
<Consumer>
{value => {
return (
<React.Fragment>
<div className="content-wrapper">
<h1>Guide Me</h1>
<div className="ms-Grid times--max-width" dir="ltr">
<div className="ms-Grid-row">
<div className="profile--wrapper ms-Grid-col ms-sm12 ms-md12 ms-lg5">
{value.guides.map(item => {
return <Guide key={item.id} guide={item} processValue={value.guides} initialGuide={value.initialGuide}/>
})}
</div>
</div>
</div>
</div>
</React.Fragment>
)
}}
</Consumer>
)
}
}
export default Guides
Process.js
import React, { Component } from 'react'
import GuideSteps from './Guide-Steps'
import { Consumer } from '../../context'
class Process extends Component {
constructor(props) {
super(props)
this.state = {
processName: this.props.guide.processName,
process: this.props.guide,
steps: this.props.guide.steps,
selectedIndex: 0,
selectedStep: '',
processValue: this.props.processValue,
initialGuide: this.props.initialGuide
}
this.displayStep = this.displayStep.bind(this)
}
displayStep = (res, dispatch) => {
this.setState({ selectedStep: res })
}
render() {
const { steps, selectedIndex, process, processName, processValue, initialGuide } = this.state
return (
<Consumer>
{value => {
return (
<div>
<h2 className="profile--sub-header--bold">{processName}</h2>
<GuideSteps
key={this.props.guide.steps[selectedIndex].id}
selectedStep={this.props.guide.steps[selectedIndex]}
stepValue={this.displayStep}
process={process}
processValue={processValue}
initialGuide={initialGuide}
/>
</div>
)
}}
</Consumer>
)
}
}
export default Process
导Steps.js
import React, { Component } from 'react'
import { ChoiceGroup } from 'office-ui-fabric-react/lib/ChoiceGroup'
import { Consumer } from '../../context'
class GuideSteps extends Component {
constructor(props) {
super(props);
this.state = {
process: [],
selectedStep: this.props.selectedStep,
dispatch: '',
processValue: this.props.processValue,
initialGuide: ''
}
this._onChange = this._onChange.bind(this)
}
_onChange = (ev, option) => {
// this.props.stepValue(option.value.nextStep)
const { dispatch , initialGuide } = this.state
let optionArray = option.value.nextStep.split(',')
let processArray = this.state.process.filter(item => {
return item.id === optionArray[0]
})
let stepArray = processArray[0].steps.filter(item => {
return item.id === optionArray[1]
})
console.log(stepArray, processArray, this.state.process, 'logging step array before setting')
processArray[0].steps = stepArray
console.log(stepArray, processArray, this.state.process, 'logging step array after setting')
dispatch({
type: 'SEARCH_PROCESS',
payload: processArray
})
}
render() {
let options = []
{
this.props.selectedStep.options.map(item => {
return options.push({
key: item.text,
text: item.text,
value: item
})
})
}
return (
<Consumer>
{value => {
const { dispatch, guides, initialGuide } = value
this.state.dispatch = dispatch
console.log(value, 'logging initial guide in render')
this.state.process = initialGuide
return (
<div>
<ChoiceGroup
className="defaultChoiceGroup"
options={options}
onChange={this._onChange}
/>
</div>
)
}}
</Consumer>
)
}
}
export default GuideSteps
在GuideSteps中进行更改是我在进行过滤和设置新对象的逻辑.
编辑
这解决了这个问题,但我认为这太贵了.如何在不重新解析数组的情况下解决此问题.
update: (ev, option) => {
const { initialGuide } = this.state
if (option.value.nextStep !== null && option.value.nextStep !== '') {
//split string
const optionArray = option.value.nextStep.split(',')
//filter process array
const processArray = initialGuide.filter(process => {
return process.id === optionArray[0]
})
//filter step array
const stepArray = processArray[0].steps.filter(
item => item.id === optionArray[1]
)
if(stepArray.length > 0 && stepArray !== null) {
//get a copy of the process array so original is not mutated by the steps
let stringC = JSON.stringify(processArray)
let stringD = JSON.parse(stringC)
stringD[0].steps = stepArray
//issue might be here visually where setting the state happens quickly, therefore radio button visual does not display in time.
setTimeout(() => {
this.setState({ guides: stringD })
}, 200)
}
}
},
解决方法:
this.state.process = initialGuide
let processArray = this.state.process.filter...
processArray[0].steps = stepArray
所以看起来你正在通过引用改变initialGuide.
标签:javascript,reactjs,state-management,react-context,react-state-management 来源: https://codeday.me/bug/20190827/1745700.html