2017-05-27 94 views
0

我尝试使用reactjs通过redux使用异步数据来创建div的动画,并且我不清楚何时可以在状态loaded上参考虚拟dom。试图在异步数据上处理与reactjs的div

在我的情况下,我有一个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); 
     } 
    } 

回答

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

+0

嗨,感谢您的反馈!我已经有一个由redux('loaded')提供的状态变量,我想依靠这个。新的状态变量如何知道异步数据是否被加载? – fefe

+0

如果你有一个'loaded'变量,你可以在'render'方法中访问它。只要做'const isHeaderOpen = this.state.loaded',然后代码是相同的。 – Gpx

+0

如果您正在学习React,我建议您在开始时不要使用Redux。只需使用组件的内部状态。一旦你了解事情的工作方式,请添加Redux或其他国家的经理。掌握所有的概念会容易得多。 – Gpx

0

如果您想要进行动画一个div为什么你想通过this.header访问它只需使用JavaScript的老式document.getElementById('header')然后你可以玩div。

+0

我没有标题。你为什么认为这会有所作为?是的,我已经尝试过,不会工作 – fefe