React Context 是道具钻井的解毒剂吗?
Is React Context an antidote for prop drilling?
如果 React Context API 是用来传递全局变量的,为什么我们要用它们来代替从父组件到子组件的传递 props(prop drilling)?由于传递的大多数道具并不意味着在应用程序范围内可用,即全局可用。
在大多数情况下,更改组件上的道具会导致它重新渲染。 Prop drilling 会减慢您的应用程序并降低其可读性。
新的 React 上下文 api 允许您“限定”值,您不必用上下文提供程序包装整个应用程序,您可以只包装组件树中您所在的部分需要特定的道具。当您的组件树嵌套很深并且您需要将某些道具传递到多个级别时,它会很有用。
上下文中定义的变量或值可用于任何试图解构这些值的组件。但是,如果您有任何更改这些定义值的设置器,则只有传递给 Provider
的 children 将获得更新的值。
例如,如果我们创建一个上下文 myContext
并定义 name
和 age
,那么我们必须设置一个提供它的提供者 children要使用的信息。
const myContext = createContext({
name: 'Bob',
age: 35
});
现在,我们可以使用 Provider 将该数据传递给 children。
function HelloWorld() {
const { Provider } = myContext;
const [age, setAge] = useState(35)
const [name, setName] = useState('Bob')
return (
<Provider value={{ name, age }}>
<Profile />
</Provider>
)
}
name
和 age
是我们想要公开给 children 的值,在这种情况下我们只有一个 child Profile
。现在我们可以通过从上下文中解构它们来访问 Profile
中的 name
和 age
。
function Profile(){
const { name, age } = useContext(myContext)
return (
<ul>
<li>{name}</li>
<li>{age}</li>
</ul>
)
}
但是假设我们项目中的其他地方有一个名为 Foo
的组件,我们想要访问 name
.
function Foo() {
const { name } = useContext(myContext) // you will only receive the default values defined in context
return <p>{name}</p>
}
这将 return 默认 'Bob' 在 myContext
中定义。你可能会想,那有什么意义呢?
如果我们更新 HelloWorld
组件以实际更新 name
和 age
onMount,Foo
仍将显示 Bob
.
function HelloWorld() {
const { Provider } = myContext;
const [age, setAge] = useState("");
const [name, setName] = useState("");
useEffect(() => {
setAge(40);
setName("Bill");
}, []);
return (
<Provider value={{ name, age }}>
<Profile />
</Provider>
);
}
function Profile() {
return (
<ul>
<li>{name}</li> // returns Bill
<li>{age}</li> // returns 40
</ul>
)
}
function Foo() {
return (
<p>{name}</p> // returns Bob
)
}
当您有独立的功能或组件需要传递数据和设置器而不是道具钻孔时,这非常有用。您可以让一个组件使用多个上下文,并且只要它们有意义,您就可以拥有任意数量的上下文。如果你只传递一次 prop,那么使用 context 是没有意义的。如果你有更复杂的道具传递,上下文可能是值得的。
如果 React Context API 是用来传递全局变量的,为什么我们要用它们来代替从父组件到子组件的传递 props(prop drilling)?由于传递的大多数道具并不意味着在应用程序范围内可用,即全局可用。
在大多数情况下,更改组件上的道具会导致它重新渲染。 Prop drilling 会减慢您的应用程序并降低其可读性。
新的 React 上下文 api 允许您“限定”值,您不必用上下文提供程序包装整个应用程序,您可以只包装组件树中您所在的部分需要特定的道具。当您的组件树嵌套很深并且您需要将某些道具传递到多个级别时,它会很有用。
上下文中定义的变量或值可用于任何试图解构这些值的组件。但是,如果您有任何更改这些定义值的设置器,则只有传递给 Provider
的 children 将获得更新的值。
例如,如果我们创建一个上下文 myContext
并定义 name
和 age
,那么我们必须设置一个提供它的提供者 children要使用的信息。
const myContext = createContext({
name: 'Bob',
age: 35
});
现在,我们可以使用 Provider 将该数据传递给 children。
function HelloWorld() {
const { Provider } = myContext;
const [age, setAge] = useState(35)
const [name, setName] = useState('Bob')
return (
<Provider value={{ name, age }}>
<Profile />
</Provider>
)
}
name
和 age
是我们想要公开给 children 的值,在这种情况下我们只有一个 child Profile
。现在我们可以通过从上下文中解构它们来访问 Profile
中的 name
和 age
。
function Profile(){
const { name, age } = useContext(myContext)
return (
<ul>
<li>{name}</li>
<li>{age}</li>
</ul>
)
}
但是假设我们项目中的其他地方有一个名为 Foo
的组件,我们想要访问 name
.
function Foo() {
const { name } = useContext(myContext) // you will only receive the default values defined in context
return <p>{name}</p>
}
这将 return 默认 'Bob' 在 myContext
中定义。你可能会想,那有什么意义呢?
如果我们更新 HelloWorld
组件以实际更新 name
和 age
onMount,Foo
仍将显示 Bob
.
function HelloWorld() {
const { Provider } = myContext;
const [age, setAge] = useState("");
const [name, setName] = useState("");
useEffect(() => {
setAge(40);
setName("Bill");
}, []);
return (
<Provider value={{ name, age }}>
<Profile />
</Provider>
);
}
function Profile() {
return (
<ul>
<li>{name}</li> // returns Bill
<li>{age}</li> // returns 40
</ul>
)
}
function Foo() {
return (
<p>{name}</p> // returns Bob
)
}
当您有独立的功能或组件需要传递数据和设置器而不是道具钻孔时,这非常有用。您可以让一个组件使用多个上下文,并且只要它们有意义,您就可以拥有任意数量的上下文。如果你只传递一次 prop,那么使用 context 是没有意义的。如果你有更复杂的道具传递,上下文可能是值得的。