我有这个
const Parent = () => {
[modalOpen, setModal] = React.useState(false);
return <Child
open={modalOpen}
closeModal={() => setModal(false)}
functionFromParent={() => console.log('Logged')} />
}
那
const Child = ({ functionFromStore, functionFromParent, closeModal }) => {
async function foo() {
try {
await ...;
functionFromStore();
functionFromParent();
} catch (error) {
....
}
}
const bar = () => {
foo();
closeModal();
}
return <div
style={{backgroundColor: 'hotpink', width: '10rem', height: '10rem' }}
onClick={() => bar()}/>
}
组件。
<Parent />
决定是否显示<Child />
(它是 Modal )。
<Child />
具有三个功能,closeModal()
和functionFromParent()
,它们来自<Parent/ >
。 functionFromStore()
从redux
到dispatchToProps()
。为了简单起见,我忽略了所有connect(stateToProps, dispatchToProps)(...)
的内容。但是,假设<Child />
直接连接到store
。
单击<div />
中的<Child/>
将执行bar()
。这导致<Child />
到unmount
,因为closeModal()
中的<Parent />
被调用,从而关闭了 modal 。但是,bar()
也调用foo()
,它是一个async
函数。
解析await
后,将调用functionFromStore()
,但不会调用functionFromParent()
。我不知道为什么呢?为什么即使卸载了组件(store
却调用了<Child />
的函数,却不是来自父级的函数呢?
此外,即使卸载了functionFromParent()
,也可以调用<Child />
吗?它可以与functionFromStore()
一起使用,是否有办法使其与functionFromParent()
一起使用?
答案 0 :(得分:1)
我无法重现您描述的行为,但是它可能是closure problem,因为您要多次设置状态,但是在处理程序的关闭状态中有过时的状态值
您可以通过将回调传递给状态设置器setSomeState(currentState=>({...currentState,changes}))
来解决,这是一个完整的示例:
function Parent() {
const [state, setState] = React.useState({
showModal: true,
showFoo: false,
});
return (
<div>
{state.showModal ? (
<Child
open={state.showModal}
closeModal={() =>
setState(state => ({
...state,
showModal: false,
}))
}
functionFromParent={() =>
setState(state => ({
...state,
showFoo: true,
}))
}
/>
) : (
'Child is gone '
)}
{state.showFoo ? <Foo /> : 'no foo'}
</div>
);
}
function Child({ functionFromParent, closeModal }) {
function foo() {
setTimeout(() => {
functionFromParent();
}, 1000);
}
const bar = () => {
foo();
closeModal();
};
return <button onClick={bar}>click me</button>;
}
function Foo() {
return 'hi, I am Foo';
}
ReactDOM.render(
<Parent />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
答案 1 :(得分:1)
functionFromParent
必须已被调用。肯定还有其他导致问题的原因。
const Parent = () => {
const [showChild, setShowChild] = React.useState(true);
const childProps = {
fnFromParent: () => {
console.log("logging from fnFromParent");
},
unmount: () => {
setShowChild(false);
}
};
return (
<div>
<p>I'm a Parent</p>
{ showChild &&
<Child {...childProps} />
}
</div>
);
};
const Child = ({ fnFromParent, unmount }) => {
const delayed = () => {
const p = new Promise(res => setTimeout(res, 3000))
p.then(() => fnFromParent());
};
const clickHandler = () => {
delayed();
unmount();
};
return <p onClick={clickHandler}>I'm a Child (click to remove me)</p>;
};
ReactDOM.render(<Parent />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
答案 2 :(得分:-1)
function Parent() {
const [modalOpen, setModal] = React.useState(false);
return (
<Child
open={modalOpen}
closeModal={() => setModal(false)}
functionFromParent={() => console.log("Logged")}
/>
);
}
是否有一种方法可以调用functionFromParent(),即使已卸载也是如此?它以某种方式与functionFromStore()一起工作,是否有办法使其与functionFromParent()一起工作?
useEffect
提供的清理。单击 div 后,将调用下面的代码,即调用 props.closeModal ,这将卸载您的 Child 组件。卸载组件后,useEffect
然后执行useEffect的return
块中的清理工作,该清理工作将调用functionFromParent
和functionFromStore
。function Child(props) {
useEffect(() => {
return () => {
props.functionFromStore();
props.functionFromParent();
};
});
return (
<div
style={{ backgroundColor: "hotpink", width: "10rem", height: "10rem" }}
onClick={props.closeModal}
/>
);
}