演示链接:http://84.201.149.106:3001/account/marketplaces
我是React和不可变状态概念的新手,我认为我可能会犯一些错误。
我有一个父组件(/帐户路径),它从服务器获取两个数据块。首先,是主块,具有步骤完成状态,我通过'steps'属性将其放入第一个子组件中。我将其setState设置为“帐户”组件状态,并根据获取的数据设置一个条件setState-如果两步的下一步状态为“下一个”,则将下一个选项卡设置为禁用。设置步骤状态后,我请求当前步骤的数据-对于我的下一个子组件,该子组件按路线(/ account / marketplaces)进行设置。获取此数据后,我在帐户组件中设置状态,并将其作为道具放入“市场”组件。
所有的路径子组件都可以在步骤视图中(用于第一个设置),就像可编辑的部分一样。我通过密钥来渲染它,这是从服务器获得的。我在此键内有节对象。它可以是“步骤”或“部分”。
这就是帐户状态:
this.state = {
loading: false,
tabs: {
marketplaces: {
component: 'Marketplace',
disabled: false,
},
company: {
component: 'Company',
disabled: false,
},
settings: {
component: 'Settings',
disabled: false,
}
},
wizard: {
active: false,
}
}
请求第一个设置并对其进行setState等...
requestWizard() {
ajax.get({
url: `${url}/settings`,
success: (resp) => {
this.setWizardState(resp.data)
}
})
}
setWizardState(data) {
Object.keys(data.steps).forEach(stepKey => {
data.steps[stepKey]['forcedOpen'] = false;
});
//after this setState I got first fully re-render of marketplace component
this.setState({wizard: {active: true, steps: data.steps}},
() => {
// it will be better to pass it like common callback from requestWizard but now it's not so important
if (this.state.wizard.steps.company.status === 'next') {
// it has next setState - see below
this.lockTab('company')
};
this.requestDataByRoute();
})
}
lockTab(key) {
this.setState(state => {
state.tabs[key].disabled = true
// I return only tabs disabled state which pass inside layout tabs property as node but react dont givafuck and re-render marketplace again
return {tabs: state.tabs}
})
}
requestDataByRoute(location) {
const {match} = this.props;
if (!location) location = this.props.location
const activeComponentKey = location.pathname.replace(match.url+'/', '');
ajax.get({
loadOverlay: this.contentWrapper.current,
url: `${url}/settings/${activeComponentKey}`,
success: (resp) => {
this.setInitialState(resp.data, activeComponentKey);
}
})
}
setInitialState(data, key) {
// some not so important methods which sets some keys for steppper or section common components
if (this.isGotSteps(data)) {
data = this.setInitialSteps(data)
} else {
data = this.setInitialSections(data)
}
this.setState((state) => {
state.tabs[key]['data'] = data
return {tabs: state.tabs}
}, () => {
// this is the last setState which sets marketplace inner step statuses from wizard
settings
this.syncWithWizardSteps(key);
})
}
这是市场子组件:
class Marketplace extends React.Component {
static whyDidYouRender = true
constructor(props) {
super(props)
this.rootEl = React.createRef();
this.bindPlaceLogField = this.bindPlaceLogField.bind(this);
this.state = this.getInitialState(props);
}
getInitialState(props) {
let data = props.data
return Object.assign({}, {...data})
}
componentDidMount() {
console.log('mounted')
}
componentDidUpdate() {
console.log('updated')
}
在市场组件内部,我得到了一个巨大的物体,如道具,它具有许多字段和其他组件,我将根据字段组件进行更改。我从props反模式中听到了初始状态的信息,但是如果不这样做怎么办?通过市场将大量回调传递到帐户,哪个具有初始状态?不,谢谢,我将无法读取代码。 因此,市场组件重新渲染五次直到初始化!为什么在任何新的setState之后重新渲染它?如果我总是检查我是否真的需要更新状态,它将不会干净。例如-我的同步向导和市场设置步骤状态的方法:
initStepStatus(stepKey, statuses) {
console.log(stepKey, statuses)
this.setState((state) => {
Object.keys(statuses.checklist).forEach(key => {
let {steps} = state.tabs[stepKey].data;
if (steps) steps[key].status = statuses.checklist[key]
})
return Object.assign({}, {tabs: state.tabs})
}, () => {
console.log('step statuses synced')
})
}
我需要再次Object.keys-重复我的代码以检查我是否真的需要setState?原因我需要检查所有状态是否与向导步骤清单相同。
反应,WTF?为什么你这么笨???
结果,我得到了 5次市场重新渲染!
我该如何解决?