Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.7k views
in Technique[技术] by (71.8m points)

reactjs - Update child component when state in parent component changes

I have a parent component which has the Hierarchy component inside it. The parent component is rendered conditionally based on the value of a variable newform in the state

    getFormRendererIO = () => {
        return (
            <div className="form-renderer-div">
                {this.state.showHierarchy ? (
                    <div className="form-renderer-div-hierarchy">
                        <Hierarchy
                            processName={this.props.processName}
                            // treeItems={HierarchyData}
                            body={this.props.body}
                            treeItems={this.state.hierarchyData}
                            openStartFormById={(e, id) => this.openStartFormById(e, id)} />
                    </div>
                ) : (
                        <div></div>
                    )}
                <div
                    className={this.state.showHierarchy ?
                        'form-renderer-div-renderer'
                        : 'form-renderer-div-renderer-without-hierarchy'}>
                    {
                        !this.state.showHierarchy ?
                            (
                                <div>
                                    <span>
                                        <FontAwesomeIcon
                                            icon={faLongArrowAltLeft}
                                            onClick={this.openLandingPage}
                                            className='backIcon'
                                            title='Back'
                                        />
                                        {/* <Button
                                            className='other-button'
                                            onClick={this.openLandingPage}>
                                            Back</Button> */}
                                    </span>
                                </div>
                            ) : (<div></div>)
                    }
                    <div>
                        <FormRendererIO
                            processInstanceId={this.props.processInstanceId}
                            body={this.state.formJson}
                            secondForm={this.props.secondForm}
                            completedTask={this.state.completedTask}
                            key={this.props.index}></FormRendererIO>
                        {
                            this.state.showHierarchy ? (
                                <span>
                                    <Button
                                        className='other-button'
                                        onClick={this.openNewForm}>
                                        New</Button>
                                    {/* <FontAwesomeIcon
                                icon={faPlus}
                                onClick={this.openNewForm}
                                className='plusIcon'
                                title='New' /> */}
                                </span>
                            ) : (<div></div>)
                        }
                    </div>
                </div>
            </div>
        );
    }

render() {
        return (
            <>
                {
                    this.state.newForm ? this.getFormRendererIO() : this.getLandingPage()
                }
            </>
        );
    }

Below is the Hierarchy component

class Hierarchy extends Component {

    state = {
        hierarchyData: []
    };

    constructor(props) {
        super(props);
    }

    getTreeItemsFromData = (treeItems, index) => {
        // var hierarchyDataStr = localStorage.getItem("hierarchyData");
        // console.log(hierarchyDataStr ? JSON.parse(hierarchyDataStr) : 'NULL');
        console.log(treeItems);
        if (treeItems.length > 0) {
            return treeItems.map((treeItemData) => {
                let children = undefined;

                if (treeItemData.children && treeItemData.children.length > 0) {
                    children = this.getTreeItemsFromData(treeItemData.children);
                }

                return (
                    <SidebarLink>
                        <StyledTreeItem
                            key={treeItemData.parent}
                            nodeId={treeItemData.parent}
                            label={treeItemData.parent === 'root' ? '' : treeItemData.parent}
                            children={children}
                            // onClick={() => handleClick(treeItemData.id)}
                            onClick={(e) => this.props.openStartFormById(e, treeItemData)}
                        />
                    </SidebarLink>
                );
            });
        }
    }

    render() {
        return (
            <TreeView
                // className={this.classes.root}
                defaultExpanded={["1"]}
                defaultCollapseIcon={<MinusSquare />}
                defaultExpandIcon={<PlusSquare />}
                defaultEndIcon={<CloseSquare />}
            >
                {this.getTreeItemsFromData(this.props.treeItems)}
            </TreeView>
        )
    };
}

export default Hierarchy;

I have an API inside the Parent componentDidMount() which updates the state of hierarchyData which is eventually passed as props in Hierarchy.

Below is the method calling the API

async getHierarchyFromAPI() {
        var formIOString = this.props.body.formIoString;
        var parentId = 'parent';
        var childId = 'child';
        var decisionId = 'decision';
        console.log(formIOString);
        if (formIOString) {
            var formIOJSON = JSON.parse(formIOString);
            var formComponents = formIOJSON.components;
            console.log(formComponents);
            for (var i = 0; i < formComponents.length; i++) {
                console.log(formComponents[i]["description"]);
                if (formComponents[i]["key"] === 'parent') {
                    parentId = this.getElementId(formComponents[i]);
                    parentId = formComponents[i]["key"];
                }
                if (formComponents[i]["name"] === 'child') {
                    childId = this.getElementId(formComponents[i]);
                    childId = formComponents[i]["name"];
                }
                if (formComponents[i]["key"] === 'decision') {
                    decisionId = formComponents[i]["key"];
                }
            }
        }

        const requestOptions = {
            method: "GET",
            credentials: "include",
        };

        let data = await fetch(localStorage.getItem("apiURL") +
            '/GRCNextBPMN/getHeirarchyData?processKey=' + this.props.processName.replace(/s+/g, "")
            + '&parent=' + parentId
            + '&child=name' //+  childId
            + '&decisionId=' + decisionId
            + '&decisionValue=Approved',
            requestOptions)
            .then(response => response.json())
        this.setState({ hierarchyData: data });
    }

The problem that I' am facing is that the API call is async and by the time the hierarchyData is updated the Hierarchy component is already rendered and the it shows as blank.

I want the hierarchyData to be updated in the Hierarchy component once the API call is finished and the component should be rendered. Please suggest a possible solution to resolve the issue

Added the componentDidMount method

componentDidMount() {
        if (this.landingPages.includes(this.props.processName)) {
            const requestOptions = {
                method: "GET",
                credentials: "include",
            };
            fetch(localStorage.getItem("apiURL") +
                '/GRCNextBPMN/getGridCols/' +
                this.props.processName.replace(/s+/g, ""),
                requestOptions)
                .then(response => response.json())
                .then(results => {
                    this.setState({
                        gridCols: results,
                        newForm: false,
                        showHierarchy: false
                    });
                })
        } else {
            this.getHierarchyFromAPI();
        }
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...