反应钩子,回调中未捕获变量



根据我的理解,每次调用setRenderer时都会执行函数Design;并且每次都会创建一个新的SyncEvent。但是,变量未在eventRef.subscribe('properties'...(中捕获。为什么回调中的渲染器为 null,但它在函数体中确实有一个值?

export class SyncEvent {
subscriber: (value: any) => void;
subscribers = new Map<string, ((value: any) => void)[]>();
subscribe(id: string, callback: (value: any) => void) {        ;
this.subscribers.set(id, [...this.subscribers.get(id) || [], callback]);
}
unsubscribe(id: string) {
this.subscribers.delete(id);
}
emit(id:string, value?: any) {
this.subscriber && this.subscriber(value);
this.subscribers.get(id)?.forEach(s => s(value));
}
}
const Design = (props: Props) => {
const eventRef = new SyncEvent();
const [renderer, setRenderer] = useState<ViewRenderer>()
const [manager] = useState(new ViewRenderer({component: PageView, isContainer: true}, eventRef))
console.log(renderer);  // not null when 2nd runs
console.log(eventRef)
eventRef.subscribe('properties', (event) => {
console.log(renderer) // <--- renderer is NULL      
setRenderer(renderer);
})
return (
<div className='design'>
<div className='design-main'>
{manager.renderComponent()}
</div>
<div className='design-right'>
<PropertiesViewPanel properties={properties}/>
</div>
</div>
);
}

问题是您直接在 render 方法中创建订阅,并且您没有在重新渲染时清理订阅。因此,具有旧闭包值的旧注册订阅仍在运行,因为您只在 setState 中分配了一次管理器实例

应使用 useEffect 来设置和清理订阅

const Design = (props: Props) => {
const [renderer, setRenderer] = useState<ViewRenderer>()
const [manager, setManager] = useState(null)
useEffect(() => {
const eventRef = new SyncEvent();
setManager(new ViewRenderer({component: PageView, isContainer: true}, eventRef));
eventRef.subscribe('properties', (event) => {   
setRenderer(renderer);
});
return () => {
eventRef.unsubscribe('properties');
}
}, [renderer]);
return (
<div className='design'>
<div className='design-main'>
{manager && manager.renderComponent()}
</div>
<div className='design-right'>
<PropertiesViewPanel properties={properties}/>
</div>
</div>
);
}

相关内容

  • 没有找到相关文章

最新更新