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