Javascript 在什么情况下,它将在使用react自定义挂钩时重新渲染
我在使用react钩子时尝试了一个示例,使其成为自定义钩子。 问题是简单的hookJavascript 在什么情况下,它将在使用react自定义挂钩时重新渲染,javascript,reactjs,typescript,frontend,react-hooks,Javascript,Reactjs,Typescript,Frontend,React Hooks,我在使用react钩子时尝试了一个示例,使其成为自定义钩子。 问题是简单的hookusecont()运行正常,但是打算切换高亮显示行的hookuseCarHighlight()不会导致重新渲染。 我看这两个都是一样的,这有什么不对吗 我在这里做了一个沙箱: 下面是一些代码: // index.tsx import * as React from "react"; import * as ReactDOM from "react-dom"; import useCarHighlight, { C
usecont()
运行正常,但是打算切换高亮显示行的hookuseCarHighlight()
不会导致重新渲染。
我看这两个都是一样的,这有什么不对吗
我在这里做了一个沙箱:
下面是一些代码:
// index.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import useCarHighlight, { Car } from "./useCarHighlight";
import useCount from "./useCount";
const myCars: Car[] = [
{ model: "C300", brand: "benz", price: 29000, ac: "auto ac" },
{ model: "Qin", brand: "byd", price: 9000 }
];
const App = () => {
const { cars, setHighlight } = useCarHighlight(myCars, "Qin");
const { count, increase, decrease } = useCount(10);
console.log(
`re-render at ${new Date().toLocaleTimeString()},
Current highlight: ${
cars.find(c => c.highlight)?.model
}`
);
return (
<div>
<ul>
{cars.map(car => {
const { model, highlight, brand, price, ac = "no ac" } = car;
return (
<li
key={model}
style={{ color: highlight ? "red" : "grey" }}
>{`[${brand}] ${model}: $ ${price}, ${ac}`}</li>
);
})}
</ul>
<button onClick={() => setHighlight("C300")}>highlight C300</button>
<button onClick={() => setHighlight("Qin")}>highlight Qin</button>
<hr />
<h1>{`Count: ${count}`}</h1>
<button onClick={() => increase()}>+</button>
<button onClick={() => decrease()}>-</button>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
// useCarHighlight.ts
import { useState } from "react";
export type Car = {
model: string;
brand: string;
price: number;
ac?: "auto ac" | "manual ac";
};
export default function(
initialCars: Car[],
initialSelectedModel: string
): {
cars: Array<Car & { highlight: boolean }>;
setHighlight: (selMod: string) => void;
} {
const carsHighlight = initialCars.map(car => ({
...car,
highlight: initialSelectedModel === car.model
}));
const [cars, setCars] = useState(carsHighlight);
const setHighlight = (selMod: string) => {
cars.forEach(car => {
car.highlight = car.model === selMod;
});
setCars(cars);
};
return {
cars,
setHighlight
};
}
// useCount.ts
import { useState } from "react";
export default function useCount(initialCount: number) {
const [state, setState] = useState(initialCount);
const increase = () => setState(state + 1);
const decrease = () => setState(state - 1);
return {
count: state,
increase,
decrease
};
}
//index.tsx
从“React”导入*作为React;
从“react dom”导入*作为react dom;
从“/useCarHighlight”导入useCarHighlight,{Car};
从“/useCount”导入useCount;
const myCars:Car[]=[
{型号:“C300”,品牌:“奔驰”,价格:29000,空调:“自动空调”},
{型号:“秦”,品牌:“比亚迪”,价格:9000}
];
常量应用=()=>{
const{cars,setHighlight}=useCarHighlight(myCars,“Qin”);
常数{计数,增加,减少}=使用计数(10);
console.log(
`在${new Date().toLocaleTimeString()}重新呈现,
当前亮点:${
cars.find(c=>c.highlight)?.model
}`
);
返回(
{cars.map(car=>{
const{model,highlight,brand,price,ac=“no ac”}=汽车;
返回(
- {`[${brand}]${model}:$${price},${ac}}
);
})}
设置高亮显示(“C300”)}>高亮显示C300
setHighlight(“Qin”)}>高亮显示Qin
{`Count:${Count}`}
增加()}>+
减少()}>-
);
};
render(,document.getElementById(“根”));
//useCarHighlight.ts
从“react”导入{useState};
出口型汽车={
型号:字符串;
品牌:弦;
价格:数量;
空调?:“自动空调”;“手动空调”;
};
导出默认函数(
姓名首字母cars:Car[],
initialSelectedModel:string
): {
汽车:阵列;
setHighlight:(selMod:string)=>void;
} {
const carsHighlight=initialCars.map(car=>({
汽车
突出显示:initialSelectedModel==car.model
}));
const[cars,setCars]=使用状态(carsHighlight);
const setHighlight=(selMod:string)=>{
cars.forEach(car=>{
car.highlight=car.model==selMod;
});
setCars(cars);
};
返回{
汽车,
设置高光
};
}
//useCount.ts
从“react”导入{useState};
导出默认函数useCount(initialCount:number){
常量[状态,设置状态]=使用状态(初始计数);
常数增加=()=>设置状态(状态+1);
常数减少=()=>设置状态(状态-1);
返回{
伯爵:国家,
增加,,
减少
};
}
与类组件不同,当使用拥有的钩子以不变的方式更新状态时,钩子的变异状态不会将重新渲染排队
此外,在基于前一状态计算下一状态时,建议使用函数更新并从函数的第一个参数读取前一状态
const setHighlight=(selMod:string)=>{
设置车辆(prevState=>
prevState.map(汽车=>({
汽车
突出显示:car.model==selMod
}))
);
};
这里有一个关于的好资源,不要在
setHighlight
中使用forEach
,而是使用map
const setHighlight = (selMod: string) => {
const newCars = cars.map(car => ({
...car,
highlight: car.model === selMod
}));
setCars(newCars);
};
使用map而不是forEach,因为在更新汽车中的highlight属性时,汽车对象的地址不会更改
const setHighlight = (selMod: string) => {
let carsTemp = cars.map(car => ({
...car,
highlight : car.model === selMod
}));
setCars(carsTemp);};
更改的嵌套字段不会导致重新渲染,但更改的对象引用会导致重新渲染。我明白了。更改嵌套字段不会导致重新渲染,但更改对象引用即可。我得到了它。谢谢你,我的英雄。