Reactjs 为什么要创建上下文而不只是导出对象?
所以我想避免道具的深度嵌套,我开始使用React上下文来实现这一点,但后来我想到“为什么我不直接导出对象呢?” 例如,不要写:Reactjs 为什么要创建上下文而不只是导出对象?,reactjs,react-hooks,Reactjs,React Hooks,所以我想避免道具的深度嵌套,我开始使用React上下文来实现这一点,但后来我想到“为什么我不直接导出对象呢?” 例如,不要写: const handleClick: = event => { event.preventDefault(); doSomething(); }; const calcPrice = (quantity) = { return quantity * 100 }; export const ComponentContext = createContext
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
对状态或道具没有任何依赖关系,那么就没有理由使用上下文。它涉及到更改状态(更改拨号)