P粉5338986942023-08-19 15:04:37
So I think the reason this is happening is that, in the ConditionalRenderComponent
component, the child elements are passed to it as properties (just like arguments to a function). JSX expressions are evaluated as arguments to functions.
This means that even if condition
is false, children
will still be evaluated before being passed to the ConditionalRenderComponent
function.
You give a child a PlayStation
(on your left hand) and a math paper score
(on your right hand) and say that if his/her score is over 90 /100, he/she will get a PlayStation.
Since the child can already see the PlayStation in your left hand (pass children
as a JSX expression), he/she has already started using it before the condition is checked.
Now, if you clench your fist, it's equivalent to passing children
as a function, and he/she can't evaluate what's in your left hand before checking whether the condition in your right hand is true.
We modify our custom component by using a function as a child element instead of rendering children
directly in the component. This way you ensure that children
is only evaluated if condition
is true.
function ConditionalRenderComponent({ condition, children }) { return ( <div> {condition && children()} </div> ); }
<ConditionalRenderComponent condition={isLoggedIn}> {() => ( <div> <p>你好,{userData.username}!</p> <p>你的电子邮件:{userData.email}</p> </div> )} </ConditionalRenderComponent>
P粉5433443812023-08-19 13:02:01
I don't recommend creating a component for conditional rendering, but if you want to do so, you can use the render properties pattern so that the function is only called when the condition is true. This prevents the expression from being evaluated immediately.
function If({ condition, render }) { if (!condition) return null; return render(); } export default function App() { const [state, setState] = useState(null); useEffect(() => { wait(1000).then(() => { setState({ hello: "world" }); }); }, []); return ( <div className="App"> <h1>Hello CodeSandbox</h1> <If condition={Boolean(state)} render={() => <p>{state.hello}</p>} /> </div> ); }