React / Redux:将jQuery事件处理程序放在组件中等待异步数据的位置

时间:2018-09-14 10:28:04

标签: javascript jquery reactjs redux

当我阅读ReactJS文档时,我了解到放置redux操作调用的最佳生命周期方法是componentDidMount,但我发现很难在该生命周期方法中执行任何jquery工作:

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isAsyncLoaded: false
        }
    }
    static getDerivedStateFromProps(nextProps, prevState) {
        let {getData} = nextProps.someData;
        let {hasSuccess, isLoading} = getData;

        if (!isLoading && hasSuccess) {
            return {
                isAsyncLoaded: true
            }
        } else {
            return {
                isAsyncLoaded: false
            }
        }

        return null;
    }
    componentDidMount() {
        this.props.getSomeData();
        $('p').css('color', 'red');
    }
    render() {
        if (!this.state.isAsyncLoaded) return null;
        return (
            <p>{this.props.someData.data}</p>
        )
    }
}

function mapStateToProps(state) {
    return {
        someData: state.someData
    }
}

export default connect(mapStateToProps, {getSomeData})(App);

在这里,jQuery $('p').css('color', 'red');部分找不到<p>元素,因为isAsyncLoaded不正确,并且render函数返回了null

我的问题是,如何在不向我的应用程序引入容器视图(父子)组件关系的情况下解决此问题?

1 个答案:

答案 0 :(得分:0)

在此之前,请注意以下几点:使用jQuery之类的事件处理程序通常是React中的反模式。它可能会对您的DOM造成意想不到的副作用,理想情况下,应完全通过react中的受控组件来处理。

但是,如果您需要使用jQuery(对于快速/肮脏的插件或类似的东西),我建议您使用单独的组件。挂载该组件后,它会触发一个componentDidMount事件,您可以挂钩并触发您的jQuery代码:

class MyJqueryComponent extends React.Component {
    constructor(props) {
        super(props);
        this.mountPoint = React.createRef();
    }
    componentDidMount() {
        // Do your jQuery stuff here
        $(this.mountPoint).find(...);
    }
    render() {
        return (
            <p ref={this.mountPoint}>{this.props.data}</p>
        );
    }
}
class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isAsyncLoaded: false
        }
    }
    static getDerivedStateFromProps(nextProps, prevState) {
        let {getData} = nextProps.someData;
        let {hasSuccess, isLoading} = getData;

        if (!isLoading && hasSuccess) {
            return {
                isAsyncLoaded: true
            }
        } else {
            return {
                isAsyncLoaded: false
            }
        }

        return null;
    }
    componentDidMount() {
        this.props.getSomeData();
        $('p').css('color', 'red');
    }
    render() {
        if (!this.state.isAsyncLoaded) return null;
        return (
            <p><MyJqueryComponent data={this.props.someData.data} /></p>
        )
    }
}

function mapStateToProps(state) {
    return {
        someData: state.someData
    }
}

export default connect(mapStateToProps, {getSomeData})(App);