尝试使用异步数据上的reactjs操作div

时间:2017-05-27 06:58:43

标签: reactjs react-redux dom-manipulation virtual-dom

我尝试通过redux使用异步数据使用reactjs为div设置动画,但我不清楚何时可以在状态loaded上引用虚拟dom。

在我的情况下,我有一个id为header的div,我希望在填充数据时按下容器。

如果我尝试使用componentDidMount而不是Cannot read property 'style' of undefined,因为componentDidMount仍然具有对加载容器的引用

class HomePage extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            sliderLength: null
        }
    }

    componentDidMount() {
        this.props.actions.getSlides()


        if(this.header) {

            setTimeout(function() {
                this.header.style.bottom = -(this.header.clientHeight - 40) + 'px';
            }, 2000);
        }
            //header.style.bottom = -pushBottom+'px';

    }


    componentWillReceiveProps(nextProps) {
        let {loaded} = nextProps
        if(loaded === true ) {
            this.animateHeader()
        }
    }

    animateHeader() {

    }

    componentWillMount() {
        const {slides} = this.props;
        this.setState({
            sliderLength: slides.length,
            slides: slides
        });
    }


    render() {
        const {slides, post, loaded} = this.props;

        if(loaded ===true ) {

            let sliderTeaser = _.map(slides, function (slide) {
                if(slide.status === 'publish') {
                    return  <Link  key={slide.id}  to={'portfolio/' + slide.slug}><img key={slide.id} className="Img__Teaser" src={slide.featured_image_url.full} /></Link>
                }
            });

            let about = _.map(post, function (data) {
                return data.content.rendered;
            })

            return (
                <div className="homePage">
                    <Slider columns={1}  autoplay={true} post={post} slides={slides} />

                    <div id="header" ref={ (header) => this.header = header}>
                        <div className="title">Title</div>
                        <div className="text-content">
                            <div dangerouslySetInnerHTML={createMarkup(about)}/>
                        </div>

                        <div className="sliderTeaser">
                            {sliderTeaser}
                        </div>

                        <div className="columns">
                            <div className="column"></div>
                            <div className="column"></div>
                            <div className="column"></div>
                        </div>

                    </div>

                    <div id="bgHover"></div>
                </div>
            );
        } else {
            return <div>...Loading</div>
        }

    }
}

function mapStateToProps(state) {
    return {
        slides: state.slides,
        post: state.post,
        loaded: state.loaded
    };
}

function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators(slidesActions, dispatch)
    };
}

function createMarkup(markup) {
    return {__html: markup};
}

export default connect(mapStateToProps, mapDispatchToProps)(HomePage);

我如何处理这种情况?

在我找到解决方案之间但不确定是否是正确的解决方法

componentDidUpdate() {
        if(this.header) {
            setTimeout(function() {
                this.header.style.bottom = -(this.header.clientHeight - 35) + 'px';
            }, 2000);
        }
    }

2 个答案:

答案 0 :(得分:0)

如果您尝试为div设置动画,为什么要尝试通过this.header访问它,只需使用javaScript的普通旧document.getElementById('header'),然后就可以使用div。< / p>

答案 1 :(得分:0)

一般情况下,尽量避免使用ref。如果你是React的新手,这一点尤其困难,但经过一些培训,你会发现自己并不需要它。

修改样式的问题就是当组件再次渲染时,您的更改将被覆盖。

我会创建一个新的state属性,比如state.isHeaderOpen。在render方法中,您将根据此标题的值来不同地呈现标题,例如:

render () {
  const {isHeaderOpen} = this.state
  return (
    <header style={{bottom: isHeaderOpen ? 0 : 'calc(100% - 40px)'}}>
  )
}

这里我使用带有百分比值的calc来获取标题的完整高度。

接下来,在您的componentDidMount中只需更新状态:

componentDidMount () {
  setTimeout(() => this.setState({isHeaderOpen: false}), 2000);
}

通过这种方式,组件将再次渲染,但具有更新的样式。

另一种方法是检查数据是否已加载,而不是创建新的state值。例如,假设您要加载一个用户列表,请在render中编写const isHeaderOpen = this.state.users != null