尝试在异步数据上使用 reactjs 操作 div
Trying to manipulate a div with reactjs on async data
我尝试通过 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);
}
}
如果您尝试为 div 制作动画,您为什么要通过 this.header
访问它,只需使用 javaScript 的普通旧 document.getElementById('header')
然后您可以玩 div.
一般来说,尽量避免使用ref
。如果您是 React 的新手,但经过一些培训,您会发现自己并不需要它,这尤其困难。
像您这样修改样式的问题在于,当组件再次呈现时,您的更改将被覆盖。
我会创建一个新的 state
属性,比如 state.isHeaderOpen
。在您的 render
方法中,您将根据此 header 的值以不同方式呈现 header 例如:
render () {
const {isHeaderOpen} = this.state
return (
<header style={{bottom: isHeaderOpen ? 0 : 'calc(100% - 40px)'}}>
)
}
我在这里使用 calc
和百分比值来获得 header.
的完整高度
接下来,在您的 componentDidMount
中简单地更新状态:
componentDidMount () {
setTimeout(() => this.setState({isHeaderOpen: false}), 2000);
}
这样,组件将再次呈现,但会使用更新后的样式。
另一种方法是检查数据是否已加载,而不是创建新的 state
值。例如,假设您要加载用户列表,在 render
中您可以写 const isHeaderOpen = this.state.users != null
.
我尝试通过 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);
}
}
如果您尝试为 div 制作动画,您为什么要通过 this.header
访问它,只需使用 javaScript 的普通旧 document.getElementById('header')
然后您可以玩 div.
一般来说,尽量避免使用ref
。如果您是 React 的新手,但经过一些培训,您会发现自己并不需要它,这尤其困难。
像您这样修改样式的问题在于,当组件再次呈现时,您的更改将被覆盖。
我会创建一个新的 state
属性,比如 state.isHeaderOpen
。在您的 render
方法中,您将根据此 header 的值以不同方式呈现 header 例如:
render () {
const {isHeaderOpen} = this.state
return (
<header style={{bottom: isHeaderOpen ? 0 : 'calc(100% - 40px)'}}>
)
}
我在这里使用 calc
和百分比值来获得 header.
接下来,在您的 componentDidMount
中简单地更新状态:
componentDidMount () {
setTimeout(() => this.setState({isHeaderOpen: false}), 2000);
}
这样,组件将再次呈现,但会使用更新后的样式。
另一种方法是检查数据是否已加载,而不是创建新的 state
值。例如,假设您要加载用户列表,在 render
中您可以写 const isHeaderOpen = this.state.users != null
.