更新状态时,React组件会重新渲染

时间:2020-07-04 08:28:02

标签: javascript reactjs react-hooks

我正在处理一个包含多个步骤的页面,根据当前步骤(由 useState 跟踪),它呈现了一个不同的组件。

我有一个父组件( App.js ),该组件跟踪所有数据更改,并且每个步骤都在其自己的组件中。在“步骤”组件中,我注意到,每当我选择一个选项时,就会发生重新渲染,并且选择丢失。 (由 Step1.js 中组件顶部的console.log观察)

如何确保不会发生重新渲染,以便正确跟踪选择?

App.js

import React, { useState } from "react";
import { Button, Space } from "antd";

import Step1 from "./Step1";

import "antd/dist/antd.css";

const Step2 = () => {
  console.log("Rendering Step 2");
  return (
    <div>
      <b>Step 2</b>
    </div>
  );
};

const Step3 = () => {
  console.log("Rendering Step 3");
  return (
    <div>
      <b>Step 3</b>
    </div>
  );
};

export default () => {
  const [step, setStep] = useState(0);
  const [items, setItems] = useState({});

  const next = () => {
    setStep(step + 1);
  };

  const prev = () => {
    setStep(step - 1);
  };

  React.useEffect(() => {
    console.log("Items:", items);
  }, [items]);

  const updateItem = (key, value) => {
    setItems({
      [key]: value
    });
  };

  const stepProps = {
    updateItem: updateItem
  };

  const StepContent = props => {
    switch (step) {
      case 0:
        return <Step1 {...props} />;
      case 1:
        return <Step2 {...props} />;
      case 2:
        return <Step3 {...props} />;
      default:
        return <b>Error</b>;
    }
  };

  const StepBar = () => {
    return (
      <div>
        <Space>
          {step > 0 && (
            <Button
              size="large"
              onClick={() => prev()}
              style={{ minWidth: "100px" }}
            >
              Previous
            </Button>
          )}
          {step < 2 && (
            <Button
              size="large"
              onClick={() => next()}
              style={{ minWidth: "100px" }}
              block
            >
              Next
            </Button>
          )}
        </Space>
      </div>
    );
  };

  return (
    <div className="App">
      <StepContent {...stepProps} />
      <StepBar />
    </div>
  );
};

Step1.js

import React from "react";
import { Radio } from "antd";

const Step1 = ({ updateItem }) => {
  console.log("Rendering Step 1");

  const onChange = event => {
    const value = event.target.value;
    updateItem("option", value);
  };

  return (
    <div>
      <Radio.Group onChange={onChange}>
        <Radio value={"a"}>A</Radio>
        <Radio value={"b"}>B</Radio>
      </Radio.Group>
    </div>
  );
};

export default Step1;

Codesandbox示例:https://codesandbox.io/s/stoic-cartwright-sr8ur

3 个答案:

答案 0 :(得分:0)

您似乎没有在Radio.Group中传递实际值,因此没有获得实际值。

在您的items中添加stepProps

const stepProps = {
    updateItem,
    items
  };

在您的Page1.js中,向已变形的道具中添加items,并向Radio.Group中添加一个价值道具,如下所示:

const Step1 = ({ items, updateItem }) => {
  console.log("Rendering Step 1");

  const onChange = event => {
    const value = event.target.value;
    updateItem("option", value);
  };

  return (
    <div>
      <Radio.Group value={items["option"] || null} onChange={onChange}>
        <Radio value={"a"}>A</Radio>
        <Radio value={"b"}>B</Radio>
      </Radio.Group>
    </div>
  );
};

最好将其他步骤也分开放在一个单独的文件中,以免造成混淆。

这是我的sandbox

答案 1 :(得分:0)

我通过登录将其检查为

StepContent= ...

无论我通过前进和后退检查的步骤如何,都将保存这些值,并且每次此方法启动时,日志都会向我显示状态,我确定该状态中存在这些值,但是我注意到的是您没有将单选组中显示的值显示为选中状态,则需要将状态传递给道具到单选组,以显示选中的按钮为选中状态

答案 2 :(得分:-1)

仅当组件的状态已更改时才能触发重新渲染。默认情况下, shouldComponentUpdate 应该返回 true

function shouldComponentUpdate(nextProps, nextState) {
        return true;
    }

这就是导致“一直更新所有内容”的原因。当React渲染组件时,它将运行 shouldComponentUpdate 并查看其是否返回true。当您使用 shouldComponentUpdate >您需要确定哪些数据真正对重新渲染很重要。

shouldComponentUpdate(nextProps) {
        return nextProps.id !== this.props.id;
    }