Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 为什么要创建上下文而不只是导出对象?_Reactjs_React Hooks - Fatal编程技术网

Reactjs 为什么要创建上下文而不只是导出对象?

Reactjs 为什么要创建上下文而不只是导出对象?,reactjs,react-hooks,Reactjs,React Hooks,所以我想避免道具的深度嵌套,我开始使用React上下文来实现这一点,但后来我想到“为什么我不直接导出对象呢?” 例如,不要写: const handleClick: = event => { event.preventDefault(); doSomething(); }; const calcPrice = (quantity) = { return quantity * 100 }; export const ComponentContext = createContext

所以我想避免道具的深度嵌套,我开始使用React上下文来实现这一点,但后来我想到“为什么我不直接导出对象呢?”

例如,不要写:

const handleClick: = event => {
  event.preventDefault();
  doSomething();
};
const calcPrice = (quantity) = {
  return quantity * 100
};
export const ComponentContext = createContext({});

export const ParentComponent = () => {
  return (
    <ComponentContext.Provider value={{ handleClick, calcPrice }}>
      <ChildComponent quantity={12} />
    </ComponentContext.Provider>

}
const handleClick:=事件=>{
event.preventDefault();
doSomething();
};
常量计算=(数量)={
退货数量*100
};
export const ComponentContext=createContext({});
导出常量ParentComponent=()=>{
返回(
}
并将其导入为:

export const ChildComponent = (quantity) = {
  const { handleClick, calcPrice } = useContext(ComponentContext);
  const totalPrice = calcPrice(quantity);
  return <button onClick={handleClick}>Total is ${totalPrice}</button>
}
const { handleSignUpClick, calcPrice } = componentProps;
export const ChildComponent = (quantity) = {
  const totalPrice = calcPrice(quantity);
  return <button onClick={handleClick}>Total is ${totalPrice}</button>
}
export const ChildComponent=(数量)={
const{handleClick,calcPrice}=useContext(ComponentContext);
施工总价=计算价格(数量);
返回总数为${totalPrice}
}
我可以简单地写为:

const handleClick: = event => {
  event.preventDefault();
  doSomething();
};
const calcPrice = (quantity) = {
  return quantity * 100
};
export const componentProps = { handleClick, calcPrice };

export const ParentComponent = () => {
  return <ChildComponent quantity={12} />
}
const handleClick:=事件=>{
event.preventDefault();
doSomething();
};
常量计算=(数量)={
退货数量*100
};
导出常量componentProps={handleClick,calcPrice};
导出常量ParentComponent=()=>{
返回
}
并将其导入为:

export const ChildComponent = (quantity) = {
  const { handleClick, calcPrice } = useContext(ComponentContext);
  const totalPrice = calcPrice(quantity);
  return <button onClick={handleClick}>Total is ${totalPrice}</button>
}
const { handleSignUpClick, calcPrice } = componentProps;
export const ChildComponent = (quantity) = {
  const totalPrice = calcPrice(quantity);
  return <button onClick={handleClick}>Total is ${totalPrice}</button>
}
const{handleSignUpClick,calcPrice}=componentProps;
导出常量ChildComponent=(数量)={
施工总价=计算价格(数量);
返回总数为${totalPrice}
}

使用上下文而不是函数有什么好处?

在您的示例中,似乎您只是在导出一些助手函数。在这种情况下,导出对象(使用这些函数)和使用
useContext()
钩子之间可能没有任何区别

但是,从React DOCs(上面的链接),我们得到:

当上下文值更改时,调用useContext的组件将始终重新呈现。如果重新呈现组件的成本很高,您可以使用记忆功能对其进行优化

如何使用导出的对象实现(重新呈现使用者)

从父级的角度来看,所有可能触发子组件重新渲染的因素都是当您使用不同的
道具
对象进行渲染时。您导出的位于组件函数之外的内容(因为您无法导出局部函数变量和“方法”)会如何执行能够更改在组件功能范围内创建的
道具
对象吗

TLDR:

基本区别在于,不能使用导出的对象重新呈现使用者子对象。至少不能在不陷入完全反模式的情况下


假设您有一个
ParentComponent
,它渲染两个昂贵的子组件,您希望为其选择大小。为此,您将使用
React.memo()
,因此仅当这些子组件的
道具发生更改时才重新渲染它们

使用上下文的将重新呈现,因为上下文属性已更改,但是使用导出变量的将不会重新呈现,因为所有已更改的都在React之外。

沙盒示例:

ParentComponent.js

import React, { useState } from "react";
import SomeContext from "./SomeContext";
import ExpensiveChildComponent from "./ExpensiveChildComponent";
import ExpensiveChildComponentExport from "./ExpensiveChildComponentExport";

let count = null; // VARIABLE THAT WILL BE EXPORTED
console.log("Outside ParentComponent...");

function ParentComponent() {
  const [myState, setMyState] = useState(0);

  console.log("Rendering Parent Component...");
  count = myState; // UPDATING THE EXPORTED VARIABLE

  function handleClick() {
    setMyState(prevState => prevState + 1);
  }

  // SETTING UP CONTEXT PROVIDER
  return (
    <div>
      <SomeContext.Provider value={myState}>
        <button onClick={handleClick}>Count</button>
        <h3>Uses Context</h3>
        <ExpensiveChildComponent />
        <h3>Uses Exported Object</h3>
        <ExpensiveChildComponentExport />
      </SomeContext.Provider>
    </div>
  );
}

console.log("After ParentComponent declaration...");

export { ParentComponent, count }; // EXPORTING COMPONENT AND VARIABLE
import React,{useState}来自“React”;
从“/SomeContext”导入SomeContext;
从“/ExpensiveChildComponent”导入ExpensiveChildComponent;
导入ExpensiveChildComponent从“/ExpensiveChildComponent导出”;
let count=null;//将导出的变量
log(“外部父组件…”);
函数ParentComponent(){
const[myState,setMyState]=useState(0);
log(“呈现父组件…”);
count=myState;//更新导出的变量
函数handleClick(){
setMyState(prevState=>prevState+1);
}
//设置上下文提供程序
返回(
计数
使用上下文
使用导出的对象
);
}
log(“在ParentComponent声明之后…”);
导出{ParentComponent,count};//导出组件和变量
ExpensiveChildComponent.js(使用上下文)

import React,{useContext}来自“React”;
从“/SomeContext”导入SomeContext;
//仅当道具或上下文发生更改时,REACT MEMO才会更新
const ExpensiveChildComponent=React.memo(函数ExpensiveChildComponent(){
log(“呈现ExpensiveChildComponent…”);
const context=useContext(SomeContext);
返回{context};
});
导出默认ExpensiveChildComponent;
ExpensiveChildComponentExport.js(使用导出的属性)

从“React”导入React;
从“/ParentComponent”;//导入导出的变量导入{count}
log(“外部ExpensiveChildComponentExport…”);
//仅当道具或上下文已更改(且两者均未使用)时,REACT MEMO才会更新
const ExpensiveChildComponent导出=React.memo(
函数ChildComponentExport(){
log(“呈现ExpensiveChildComponentExport…”);
返回(
{count}
);
}
);
导出默认ExpensiveChildComponent导出;
结果:

注意:

如果从ExpensiveChildComponent导出中删除
React.memo
,它将重新渲染,因为React会在每次渲染时创建一个新的
props
对象(它将是一个空对象,但每次都是不同的对象)。这就是我添加
React.memo()的原因
,因为它将对
道具
对象执行肤浅的比较。因此我可以说明
useContext
具有的行为,而仅导出的对象没有。

什么是
doSomething()
handleClick
中需要做什么?这似乎不太可能对应用程序状态没有某种依赖关系。如果
handleClick
对状态或道具没有任何依赖关系,那么就没有理由使用上下文。它涉及到更改状态(更改拨号)