我有多层 React 组件,用于从音乐服务 API 获取嵌入,包括一个点击 API 来填充嵌入的高阶组件。我的问题是我的最低级别的子组件不会改变状态。我基本上希望填充的嵌入(最低级别的组件)显示一个专辑封面,单击它后消失(显示 iframe),并且其状态保持稳定,除非更高的 props 发生任何变化(当该组件显示时,有除了焦点更高之外应该没有其他状态变化)。代码如下:
父级:
return (
/*...*/
<Embed
embed={this.props.attributes.embed}
cb={updateEmbed}
/>
/*...*/
第一个 child (上面):
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}
/>;
/*...*/
使用API:
/*...*/
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}
/>
)
}
最后一个我感兴趣的 child :
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 之类的东西,但我真的觉得我不需要这样做,而且我在这里缺少一些基本的东西。
最佳答案
问题在于 const WithAPIEmbed = withAPI( Embed );
位于 render 方法内部。这会在每个渲染上创建一个新的 WithAPIEmbed
对象,该对象将被重新安装,并清除下面的任何状态。将其从类定义中取出使其稳定并解决问题。
关于javascript - 为什么子组件的状态不断清除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49342535/