使用ajax调用React组件 - 生命周期

时间:2016-05-01 16:06:35

标签: javascript ajax reactjs lifecycle

所以我有一个使用Ajax调用的反应的有趣案例。

要把它放在上下文中,我有一个带有3个标签的手风琴。初始化Accordion react组件后,我首先打开第一个标签,其余标签关闭。 每个标签都有一个所谓的DictionaryCall组件,如下所示:

return class DictionaryCall extends React.Component {

        constructor (props) {
            super();
            this.state = {
                word: '',
                data: [],
                error: false,
                nodata: false,
                initialLoaded: props.load
            }
        }

        componentDidMount () {
            if(this.state.initialLoaded){
                this.callAjax();
            }
        }

        componentWillReceiveProps (nextProps) {
            if(nextProps.load){
                this.setState({initialLoaded: true});
                this.callAjax();
            }
        }

        callAjax () {
            $.ajax({
                url: this.props.url,
                dataType: 'json',
                catche: false,
                method: 'POST',
                data: {word: this.props.word},
                success: function(data){
                    if(!data.length){
                        this.setState({nodata: true});
                    } else {
                        this.setState({data: data});
                    }
                }.bind(this),
                error: function(xhr, status, error){
                    console.log(this.props.url, status, error.toString());
                    this.setState({error: true});
                }.bind(this)
            });
        }

        render () {
            let body,
                error = this.state.error;

            if(this.state.nodata){
                body = <div>No definition found</div>
            } else {
                body = <DataTab data={this.state.data} title={this.props.word}/>
            }

            return (
                <div className="dictionary-call">
                    {body}
                    {error ? <ServerError onClick={this.callAjax.bind(this)}/> : null}
                </div>
            )
        }
    };

根据React docs设置具有props的初始状态的所有拳头都是反模式,直到您明确指定它仅用于组件初始化。

因此,在构造函数中可以看到,我将initialLoaded状态设置为props.load。我将props.load仅作为true传递给第一个“手风琴”标签,因为我希望它最初加载。

调用

componentDidMount方法并检查initialLoaded状态。如果它设置为true,则只需调用ajax并重新呈现该组件。

现在是棘手的一点。 componentWillReceiveProps方法。我期待,当用户点击“Accordion”标签打开它时,该组件将会收到nextProps.load。然后props.load传递给true值的组件。

我的问题是componentWillReceivePropsthis.callAjax()打电话的好地方吗?在这种情况下创建initalLoaded状态似乎有点无意义。我不应该仅仅依靠props.load并致电shouldComponentUpdate吗?

或者我应该坚持使用initalLoaded州并使用componentWillUpdatecomponentDidUpdate

请记住,当手风琴标签第一次打开时,我只想调用一次ajax调用。

谢谢!

1 个答案:

答案 0 :(得分:5)

经过一番研究后,我想回答我自己的问题。希望它可以帮到某人。

解决方案非常简单和干净(在我看来)。

        componentDidMount () {
            if(this.state.initialLoaded){
                this.callAjax();
            }
        }

        componentWillReceiveProps (nextProps) {
            if(nextProps.load){
                this.setState({initialLoaded: true});
            }
        }

        componentWillUpdate (nextProps, nextState) {
            if(this.state.initialLoaded !== nextState.initialLoaded) {
                this.callAjax();
            }
        }

此代码适用于组件的所有实例,无论它是第一个手风琴选项卡(最初打开)还是其余选项卡(最初关闭)的子项。

componentDidMount方法中,我正在检查组件是否应该进行Ajax调用。如果在初始化期间this.props.open已将this.state.initialLoaded状态设置为true,则进行ajax调用。当然不是。

现在,当用户点击其他标签时,该组件需要componentWillReceiveProps中的道具。这里我只在nextProps.load为真时才设置状态,因为我只想在load字段为真时加载数据。

最后,如果componentWillReceiveProps中的条件已满足,我正在检查this.state.initialLoaded是否已更改。因为它只有在nextProp.load为真时才能更改,它会阻止多次调用Ajax请求(当状态从true变为false时)。

这样,我只在第一次打开选项卡或最初打开选项卡时调用Ajax请求。

那很简单!