React:更新数组中的组件

时间:2018-06-12 14:52:55

标签: reactjs

我有一个包含子组件数组的React组件。父级从服务检索数据并将其存储在状态中。它通过props将数据从数据数组传递给每个子组件。

子组件包含更新其数据项中的值的功能。当它执行此操作时,它会触发一个事件,将更新的项目传递回父项。父级创建一个新的状态数组,包括更新的项目。

以下简化代码。

一切正常,更新数组在父的render方法中处理。但是,子组件永远不会重新呈现,因此更新的属性保持其先前的值。

如何让相关的子组件显示更新后的状态?

class SearchView extends Component {
    pageSize = 20;

    constructor(props) {
        super(props);
        this.state = { 
            searchTerm: this.props.searchTerm, 
            results: []
        };                
    }

    getResults = (page) => {  
        const from = (page - 1) * this.pageSize;
        searchActions.termSearch(this.state.searchTerm, from, this.pageSize).then(response => { 
            const results = response.SearchResultViews;
            this.setState({ 
                results: results
            });
        });    
    }

    componentDidMount() {
        this.getResults(1);
    }

    refresh(result){
        const results = this.state.results.map(r => {
            return (r.Id === result.Id) ? result : r;
        });
        this.setState({
            results: results
        });
    }

    render() {
        let items = [];
        if (this.state.results.length > 0) {
            items = this.state.results.map((result, i) => {
                return <SearchItem key={i} result={result} onStatusUpdate={(r) => this.refresh(r)}></SearchItem>;
            });    
        }

        return (
            <div className="r-search-result">
                <Row className='clearfix scroller'>                        
                    <div className='r-container-row results'>        
                        { items }
                    </div>
                </Row>
            </div>
        );
    }
}

class SearchItem extends Component {
    constructor(props) {
        super(props);
    }

    updateStatus(newValue) {
        resourceActions.updateStatus(newValue);
        //Bubble an event to the Parent to refresh the result and view   
        if (props.onStatusUpdate) {
            searchActions.get(props.result.Id).then((result) => {
                props.onStatusUpdate(result);
            });    
        }
    }

    render() {
        return (                                    
            <a href={this.props.result.link}>
                <span className="column icon-column">{this.props.result.imageUrl}</span>
                <span className="column title-column">{this.props.result.titleLink}</span>
                <span className="column status-column">{this.props.result.status}</span>
                <span className="column button-column"><button onClick={() => this.UpdateStatus(5)}></button></span>
            </a>
        );
    }
}

修改 在我的实际(非简化)应用程序中,子组件转换它在ComponentDidMount()方法中传递的道具,并在状态中设置值; render方法将标记绑定到state,而不是props。在@Vishal在评论中建议的孩子的Render()方法中设置断点后,我可以看到孩子收到更新的数据,但由于状态尚未更新,该组件不显示更新的数据。

那么问题是,如何更好地更新组件状态而不会导致无限渲染循环?

1 个答案:

答案 0 :(得分:1)

最后,我通过将属性转换为componentWillUpdate()中子组件的状态以及componentDidMount()方法来解决问题。如下面的代码所示:

componentDidMount() {
    if (this.props.result) {
        this.prepareRender();
    }
}

componentWillUpdate(nextProps, nextState) {
    if (nextProps.result.status!== this.props.result.status) {
        this.prepareRender();
    }
}

prepareRender() {
    //simplified
    this.setState({
        imageUrl: this.props.result.imageUrl,
        titleLink: this.props.result.titleLink,
        status: this.props.result.status
    });
}

render() {
    return (                                    
        <a href={this.props.result.link}>
            <span className="column icon-column">{this.state.imageUrl}</span>
            <span className="column title-column">{this.state.titleLink}</span>
            <span className="column status-column">{this.state.status}</span>
            <span className="column button-column"><button onClick={() => this.UpdateStatus(5)}></button></span>
        </a>
    );
}

<强>更新

在React 16.3中,不推荐使用componentWillUpdate()方法。此解决方案应使用新的getDerivedStateFromProps()生命周期方法,如下所述:https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html