当我更新父级内部的状态时,为什么反应组件树开始完全重新渲染?

时间:2019-11-12 10:28:30

标签: javascript reactjs

演示链接: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次市场重新渲染!
我该如何解决?

0 个答案:

没有答案