【问题标题】:Trying to manipulate a div with reactjs on async data尝试在异步数据上使用 reactjs 操作 div
【发布时间】:2017-10-28 01:53:29
【问题描述】:

我尝试通过 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);
        }
    }

【问题讨论】:

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


    【解决方案1】:

    一般来说,尽量避免使用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

    【讨论】:

    • 您好,感谢您的反馈!我已经有一个由 redux(loaded) 操作提供的状态变量,我想依赖它。新的状态变量如何知道是否加载了异步数据?
    • 如果你有一个loaded 变量,你可以在render 方法中访问它。只要做const isHeaderOpen = this.state.loaded,然后代码是一样的。
    • 如果你正在学习 React,我建议你一开始不要使用 Redux。只需使用组件的内部状态。一旦你了解了事情是如何工作的,添加 Redux 或其他一些状态管理器。掌握所有概念会容易得多。
    • 好的,这会起作用,但这不允许我对 DOM 元素进行计算。正如我所读到的,它们是了解组件是否重新渲染的几种方法(`componentWillReciveProps, componentDidUpdate``)
    • 我做了一个小bin,看看能不能帮澄清一下webpackbin.com/bins/-Kl8ZDcdkkTQJpBb0Bdd
    【解决方案2】:

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

    【讨论】:

    • 我没有标题。为什么你认为这会有所作为。是的,我已经尝试过了,不会工作
    猜你喜欢
    • 2022-01-20
    • 2020-04-23
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 2017-03-03
    • 2020-10-30
    • 1970-01-01
    • 2016-06-17
    相关资源
    最近更新 更多