0

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

就我而言,我有一个带有 id 的 div header,我想在填充数据时向下推容器。

如果我尝试在 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);
        }
    }
4

2 回答 2

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.

于 2017-05-27T08:32:27.990 回答
0

如果您尝试为 div 设置动画,为什么要尝试通过this.header使用 javaScript 的普通旧版本来访问它document.getElementById('header'),然后您可以使用 div。

于 2017-05-27T07:24:12.470 回答