2017-05-27 90 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