为何访问属性时我的NotEmpty高阶组件(HOC)无法正常工作?
thread.title in my NotEmpty HOC's children throw a TypeError? I've built a simple NotEmpty Higher-Order Component (HOC) to conditionally render children only when a given value isn't null or undefined:
const NotEmpty = ({value, children}) => { return (value ? children : null); };
This works perfectly when the children don't depend on the value prop:
<NotEmpty value={thread}> <p>Hello World</p> </NotEmpty>
But when I try to access a property of thread inside the children, it throws an error:
<NotEmpty value={thread}> <p>{thread.title}</p> </NotEmpty>
Error message:
Uncaught TypeError: Cannot read property 'title' of undefined
What's going wrong here?
Answer:
The core issue is the order of JSX evaluation in React.
When you write JSX like <p>{thread.title}</p>, the expression thread.title gets resolved before the NotEmpty component runs its conditional logic. React first evaluates all child elements and expressions passed to a component, then passes the finished React elements to the parent as the children prop.
So even if thread is undefined, React tries to compute thread.title immediately when it parses the NotEmpty component's children—before checking if value is truthy in the NotEmpty component. That's why you hit the "Cannot read property 'title' of undefined" error.
How to fix this?
The standard solution is to modify your NotEmpty component to accept a function as children instead of pre-rendered React elements. This lets you delay evaluating the child logic until the component confirms the value is safe to use:
const NotEmpty = ({ value, children }) => { // Only execute the children function if value is truthy return value ? children(value) : null; };
Then use it like this:
<NotEmpty value={thread}> {/* We receive the valid thread as an argument here */} {(thread) => <p>{thread.title}</p>} </NotEmpty>
This works because the function won't run until NotEmpty verifies value is truthy. If thread is undefined, the function never executes, so thread.title is never evaluated.
As an alternative, if you want to keep the original component structure, you can add a guard clause directly in the child expression using optional chaining:
<NotEmpty value={thread}> <p>{thread?.title}</p> </NotEmpty>
The ?. operator prevents the error by returning undefined instead of throwing when thread is null/undefined. Note that this will still render the <p> tag (with empty content) if thread is falsy, which might not align with your original goal of not rendering the children at all.
内容的提问来源于stack exchange,提问作者cdxf

