很遗憾,我认为您想要实现的目标可能无法直接达成,但您可以采取一种类似功能的变通方法。换种思路:与其添加和移除子组件(Child)的外层包裹(Parent),不如尝试添加和移除其同级元素。这在本质上是相同的操作。虽然您提到不想修改 <Parent>
组件的代码,但我认为这样做并不会对您的代码产生太大影响。
以下是一个示例:
const Parent = ({ children, state }: { children: ReactNode; state: number }) => {
return (
<>
{state % 2 === 0 ? (
<>
<label>Sibling 1</label>
<div>Sibling 2</div>
</>
) : (
""
)}
{children}
</>
);
};
如您所见,我没有对整体结构做大幅改动,只是添加和移除了同级元素。
另外,请记得在子组件中使用 useMemo
:
const Child = () => {
const [childState, setChildState] = useState<number>(0);
return useMemo(() => {
console.log("Child re-render");
return (
<button
onClick={() => {
setChildState(childState + 1);
}}
>
Child State: {childState}
</button>
);
}, [childState]);
};
在这个例子中,子组件仅应在 childState
改变时重新渲染。如果父组件的状态改变,应仅重新渲染同级元素。以下是完整的代码:
import { ReactNode, useMemo, useState } from "react";
const App = () => {
const [appState, setAppState] = useState<number>(0);
return (
<>
<button
onClick={() => {
setAppState(appState + 1);
}}
>
test
</button>
<Parent state={appState}>
<Child />
</Parent>
</>
);
};
const Parent = ({ children, state }: { children: ReactNode; state: number }) => {
return (
<>
{state % 2 === 0 ? (
<>
<label>Sibling 1</label>
<div>Sibling 2</div>
</>
) : (
""
)}
{children}
</>
);
};
const Child = () => {
const [childState, setChildState] = useState<number>(0);
return useMemo(() => {
console.log("Child re-render");
return (
<button
onClick={() => {
setChildState(childState + 1);
}}
>
Child State: {childState}
</button>
);
}, [childState]);
};
export default App;