Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.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
Javascript 在什么情况下,它将在使用react自定义挂钩时重新渲染_Javascript_Reactjs_Typescript_Frontend_React Hooks - Fatal编程技术网

Javascript 在什么情况下,它将在使用react自定义挂钩时重新渲染

Javascript 在什么情况下,它将在使用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

我在使用react钩子时尝试了一个示例,使其成为自定义钩子。 问题是简单的hook
usecont()
运行正常,但是打算切换高亮显示行的hook
useCarHighlight()
不会导致重新渲染。 我看这两个都是一样的,这有什么不对吗

我在这里做了一个沙箱:

下面是一些代码:

// 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);};

更改的嵌套字段不会导致重新渲染,但更改的对象引用会导致重新渲染。我明白了。更改嵌套字段不会导致重新渲染,但更改对象引用即可。我得到了它。谢谢你,我的英雄。