感谢您看到这个问题,也感谢您对这个问题的思考
我正在寻找为 React.js 中的整个子组件提供特定道具的方法
我知道在这种情况下,我们通常使用 context 或像 recoil 这样的存储包,并从下面的子组件中获取数据。
在这个例子中,父组件通过上下文将
disabled
状态传递给子组件,子组件使用useContext
使用提供的数据。
const DisableContext = createContext({});
const ParentComponent = () => {
const [disabled, setDisabled] = useState(false);
return (
<DisableContext.Provider value={{ disabled }}>
<button onClick={() => setDisabled((old) => !old)}>{disabled ? 'Disabled' : 'Enabled'}</button>
<ChildComponent />
</DisableContext.Provider>
)
}
const ChildComponent = () => {
const { disabled } = useContext(DisableContext);
return (
<div>
<p>ChildComponent</p>
<span>Parent is {disabled ? 'Disabled' : 'Enabled'}</span>
<GrandChildComponent />
</div>
)
}
const GrandChildComponent = () => {
const { disabled } = useContext(DisableContext);
return (
<div>
<p>GrandChildComponent</p>
<span>Parent is {disabled ? 'Disabled' : 'Enabled'}</span>
</div>
)
}
但在我的例子中,我想将数据传递给整个子组件
props
。而且我不想在每个子组件中编写消费代码(在这种情况下为useContext
)。
我知道
cloneElement
可以覆盖子组件的原始道具,并且可以使用它来传递道具而无需在子组件中编码消费代码,如下所示。
然而,在下面的例子中,孙子组件无法监听祖父组件 props 的变化。只有直接子组件才能通过 props 监听
disabled
或者,我们可以递归地应用
cloneElement
将道具传递给整个子组件。但我知道这可能是一个繁重的过程,我想避免这种模式。
有什么好的方法可以达到我的要求吗?
const DisableWrapperComponentWhichPassesDisabledAsProps = ({ children, disabled }) => {
return cloneElement(children, { disabled })
}
const ParentComponent = () => {
const [disabled, setDisabled] = useState(false);
return (
<>
<button onClick={() => setDisabled((old) => !old)}>{disabled ? 'Disabled' : 'Enabled'}</button>
<DisableWrapperComponentWhichPassesDisabledAsProps disabled={disabled}>
<ChildComponent />
</DisableWrapperComponentWhichPassesDisabledAsProps>
</>
)
}
const ChildComponent = ({ disabled }) => {
return (
<div>
<p>ChildComponent</p>
<span>Parent is {disabled ? 'Disabled' : 'Enabled'}</span>
<GrandChildComponent />
</div>
)
}
const GrandChildComponent = ({ disabled }) => {
return (
<div>
<p>GrandChildComponent</p>
<span>Parent is {disabled ? 'Disabled' : 'Enabled'}</span>
</div>
)
}
[我试过的]
cloneElement
试过,但我发现它不能满足我的要求。[我期待的]
disabled
作为道具,没有任何特殊的消费代码,如useContext
或其他东西。道具可以根据需要向下传递。这样的事情应该可以解决问题:
const ParentComponent = () => {
const [disabled, setDisabled] = useState(false);
return (
<button onClick={() => setDisabled((old) => !old)}>{disabled ? 'Disabled' : 'Enabled'}</button>
<ChildComponent disabled={disabled} />
)
}
const ChildComponent = ({ disabled }) => {
return (
<div>
<p>ChildComponent</p>
<span>Parent is {disabled ? 'Disabled' : 'Enabled'}</span>
<GrandChildComponent disabled={disabled} />
</div>
)
}
const GrandChildComponent = ({ disabled }) => {
return (
<div>
<p>GrandChildComponent</p>
<span>Parent is {disabled ? 'Disabled' : 'Enabled'}</span>
</div>
)
}