Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/71.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 - Fatal编程技术网

仅更改状态对象属性时是否可能触发ReactJs组件重新渲染?

仅更改状态对象属性时是否可能触发ReactJs组件重新渲染?,reactjs,Reactjs,我正在学习ReactJs,在尝试useState和useContext钩子时遇到了一些问题。似乎只有在引用更改而不是值更改时才会发生重新渲染。以下面的代码为例: 类计数器{ 计数:数字; 构造函数(计数:个数){ this.count=计数; } 增加{ 这是1.count+=1; } } 导出常量CountComponent:FC=(道具)=>{ //const[count,setCount]=useState(0);//工时 //const[count,setCount]=useState

我正在学习ReactJs,在尝试
useState
useContext
钩子时遇到了一些问题。似乎只有在引用更改而不是值更改时才会发生重新渲染。以下面的代码为例:

类计数器{
计数:数字;
构造函数(计数:个数){
this.count=计数;
}
增加{
这是1.count+=1;
}
}
导出常量CountComponent:FC=(道具)=>{
//const[count,setCount]=useState(0);//工时
//const[count,setCount]=useState({0});//work
const[counter]=useState(新计数器(0));//不工作
常量doAdd=()=>{
计数器增加();
控制台日志(计数器计数);
}
//这实际上不会重新渲染
返回({counter.count}+);
}
单击按钮时,计数已增加,但渲染的值未更新。我有什么遗漏吗?有没有办法让组件监视状态对象属性的更改

编辑

我想我把人们和这个问题的意图搞混了。考虑一个更复杂的用例,我有一个复杂的状态对象。请原谅我的密码:

class Cargo {
    orders: Map<string, Products[]>;
    totalValue: number;
    totalNumber: number;

    addProduct(product: Product) {
      // ignore the null check here.
      this.orders.get(product.owner).push(product);
      this.totalValue += product.value;
      this.totalNumber ++;
    }
}

class Product {
   owner: string;
   name: string;
   value: number;
}

const CargoContext = createContext(new Cargo());

const CargoContext = createContext({... new Cargo(), setTotalValue, setTotalNumber});

// lost the OO
const {orders, totalValue, totalNumber, setTotalValue, setTotalNumber} = useContext(CargoContext);

const doAdd = (product: Product) => {
   orders.get(product.owner); 
   setTotalValue(product.value);
   setTotalNumber(totalNumber + 1);
}

class货物{
订单:地图;
totalValue:数字;
总数:数字;
添加产品(产品:产品){
//忽略此处的空检查。
this.orders.get(product.owner).push(product);
this.totalValue+=product.value;
这个是.totalNumber++;
}
}
类产品{
所有者:字符串;
名称:字符串;
值:数字;
}
const-CargoContext=createContext(new-Cargo());
const-CargoContext=createContext({…new Cargo(),setTotalValue,setTotalNumber});
//丢失了OO
const{orders,totalValue,totalNumber,setTotalValue,setTotalNumber}=useContext(CargoContext);
const doAdd=(产品:产品)=>{
orders.get(product.owner);
setTotalValue(产品值);
setTotalNumber(totalNumber+1);
}

以这种方式创建上下文时,我实际上无法更新状态。从我所读到的内容来看,使其工作的唯一方法是解构Cargo对象并传递属性和dispatcher。但这样就失去了面向对象的
Cargo
addProduct
接口。如何更优雅地处理这种情况?

在处理这样的复杂状态时,最好使用
useReducer
。为了配合您的货物示例,它需要

interface CargoState {
    orders: Map<string, Products[]>;
    totalValue: number;
    totalNumber: number;
}

const cargoReducer = (state: CargoState, action): CargoState => {
   switch (action.type) {
       case 'add-product': {
           const newOrders = state.orders;
           newOrders.get(action.product.name).push(action.product);

           return {
               ...state,
               orders: newOrders,
               totalValue: state.totalValue + product.value,
               totalNumber: state.totalNumber++,
           }
       }
       default: return state;
    }
}



const [state, dispatch] = useReducer(cargoReducer, [some initial state here]);


dispatch({ type: 'add-product', product });
接口状态{
订单:地图;
totalValue:数字;
总数:数字;
}
const-cargoReducer=(状态:CargoState,操作):CargoState=>{
开关(动作类型){
案例“添加产品”:{
const newOrders=state.orders;
newOrders.get(action.product.name)、push(action.product);
返回{
……国家,
订单:新订单,
totalValue:state.totalValue+product.value,
totalNumber:state.totalNumber++,
}
}
默认:返回状态;
}
}
const[state,dispatch]=useReducer(cargoReducer,[此处的一些初始状态]);
分派({type:'add product',product});

操作可以正确键入,因此不会丢失任何键入。

您没有正确使用状态。如果您不告诉React状态已更改,它如何知道状态已更改?您需要使用
setCounter
功能。update函数的作用不仅仅是更改状态值。它要求React比较新旧值,如果它们不同,则安排渲染。比较也是一种浅层比较,因此,由于您的状态是一个对象,因此ref需要更改,而不仅仅是其中的一个值。
useState
返回两个内容-其当前值和updater函数。您应该使用
const[counter,setCounter]…
解构,并使用
setCounter
更新该状态,这将触发重新渲染。好消息是它实际上比您所做的更容易!
计数器
类是不必要的。只要给
useState
一个
0
的初始值,你就可以开始了!(同时也遵循上述建议)感谢您的投入。我意识到我没有准确地表达我的意图。我已经编辑了我的问题。我相信你的问题是你在写函数代码,但试图使用OO范式。只需坚持功能性方法。此外,您的上下文需要一个提供者,而您目前还没有。您的提供者应该将货物属性存储在state中,并通过上下文apithou@topchd公开它们。这是一个伟大的解决方案!
interface CargoState {
    orders: Map<string, Products[]>;
    totalValue: number;
    totalNumber: number;
}

const cargoReducer = (state: CargoState, action): CargoState => {
   switch (action.type) {
       case 'add-product': {
           const newOrders = state.orders;
           newOrders.get(action.product.name).push(action.product);

           return {
               ...state,
               orders: newOrders,
               totalValue: state.totalValue + product.value,
               totalNumber: state.totalNumber++,
           }
       }
       default: return state;
    }
}



const [state, dispatch] = useReducer(cargoReducer, [some initial state here]);


dispatch({ type: 'add-product', product });