React Context 是props钻孔的解药吗?

IT技术 reactjs react-context use-context
2021-05-06 00:34:23

如果 React Context API 旨在用于传递全局变量,我们为什么要使用它们来替代从父组件到子组件的传递props(props钻取)?由于大多数传递的props并不意味着在应用程序范围内可用,即全局可用。

3个回答

上下文中定义的变量或值可用于任何试图解构这些值的组件。但是,如果您有任何更改这些定义值的 setter,则只有传递给 的子项Provider才会获得更新的值。

例如,如果我们创建一个上下文myContext并定义nameand age,那么我们必须设置一个提供者,该提供者将为它的孩子提供要消费的信息。

const myContext = createContext({ 
  name: 'Bob',
  age: 35
});

现在,我们可以使用 Provider 将这些数据传递给孩子。

function HelloWorld() { 
 const { Provider } = myContext;
 const [age, setAge] = useState(35)
 const [name, setName] = useState('Bob') 
 return (
   <Provider value={{ name, age }}>
     <Profile />
   </Provider>
 )
}

name并且age是我们想要呈现给我们的孩子的value观,在这种情况下,我们只是有一个孩子Profile现在我们可以通过从我们的上下文中解构它们来访问nameage进入Profile

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>
}

这将返回中定义的默认“Bob” myContext你可能会想,这样做有什么意义?

如果我们更新我们的HelloWorld组件以实际更新nameageonMount,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 
 )
}

当您有需要传递数据和 setter 而不是 prop 钻探的孤立功能或组件时,这非常有用。您可以让一个组件使用多个上下文,并且您可以拥有任意数量的上下文,只要它们有意义即可。如果您只传递一次props,则使用上下文没有意义。如果你有更复杂的props传递,上下文可能是值得的。

新的 react 上下文 api 允许您“限定”值,您不必使用上下文提供程序包装整个应用程序,您可以只包装组件树中需要特定props的部分。当您的组件树嵌套很深并且您需要将某些 props 传递到多个级别时,它会很有用。

在大多数情况下,更改组件上的 props 会导致它重新渲染。props钻孔会减慢您的应用程序并降低其可读性。