我有多层React组件,用于从音乐服务API获取嵌入,包括命中API以填充嵌入的高阶组件。我的问题是我的最低级别的子组件不会改变状态。我基本上希望填充的嵌入(最低级别组件)显示专辑封面,在单击它后显示消失(显示iframe),并且其状态保持稳定,除非道具更高的任何变化(到此组件显示时,那里应该没有其他状态的变化,除了焦点更高)。这是代码:
父:
return (
/*...*/
<Embed
embed={this.props.attributes.embed}
cb={updateEmbed}
/>
/*...*/
第一个孩子(上图):
render() {
const {embed, className, cb} = this.props;
const {error, errorType} = this.state;
const WithAPIEmbed = withAPI( Embed );
/*...*/
return <WithAPIEmbed
embed={embed[0]}
className={className}
cb={cb}
/>;
/*...*/
withAPI:
/*...*/
componentWillMount() {
this.setState( {fetching: true} );
}
componentDidMount() {
const {embed} = this.props;
if ( ! embed.loaded ) {
this.fetchData();
} else {
this.setState( {
fetching: false,
error: false,
} );
}
}
fetchData() {
/*... some API stuff, which calls the callback in the top level parent (cb()) setting the embed prop when the promise resolves -- this works just fine ...*/
}
render() {
const {embed, className} = this.props;
const {fetching, error, errorType} = this.state;
if ( fetching ) {
/* Return some spinner/placeholder stuff */
}
if ( error ) {
/* Return some error stuff */
}
return (
<WrappedComponent
{...this.props}
embed={embed}
/>
)
}
最后,我感兴趣的是最后一个孩子:
constructor() {
super( ...arguments );
this.state = {
showCover: true,
};
}
render() {
const {embed, setFocus, className} = this.props;
const {showCover} = this.state;
if ( showCover ) {
return [
<div key="cover-image" className={classnames( className )}>
<figure className='cover-art'>
<img src={embed.coverArt} alt={__( 'Embed cover image' )}/>
<i onClick={() => {
this.setState( {showCover: false,} );
}}>{icon}</i> // <-- Play icon referenced below.
</figure>
</div>,
]
}
return [
<div key="embed" className={className}>
<EmbedSandbox
html={iframeHtml}
type={embed.embedType}
onFocus={() => setFocus()}
/>
</div>,
];
}
我的问题是点击播放图标应该清除专辑封面并显示嵌入的iframe,但即使点击正在注册,状态也不会改变(或者会改变然后再改变)。我相信它是因为更高级别的组件正在安装/卸载并以其默认状态重新实例化该组件。我可以把这个状态移到树上或使用像Flux这样的东西,但我真的觉得我不应该这样做,而且我在这里缺少一些基本的东西。
答案 0 :(得分:1)
问题是const WithAPIEmbed = withAPI( Embed );
在render方法中。这将在每个渲染上创建一个新的WithAPIEmbed
对象,该对象将被重新安装,清除下面的任何状态。将它从类定义中提取出来可以使它稳定并解决问题。