React组件在状态更新时自动重新安装,为什么?

时间:2019-09-26 14:39:34

标签: javascript reactjs

我有一个父React.js组件,将状态和设置器传递给子组件。

每次子组件使用设置器时,都会卸载并重新安装子组件。 我是新来的反应者,我不知道发生了什么。

const useState = React.useState;

class MyComponnent extends React.Component {
  intervalID = null;

  componentDidMount() {
    console.log("MOUNTING");
    this.intervalID = setInterval(() => {
      this.props.setA({ a: this.props.a.a + 1 });
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.intervalID);
  }

  render = () => {
    return (
      <div
        style={{
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          flexDirection: "column"
        }}
      >
        <div
          style={{
            flexDirection: "row",
            display: "flex",
            justifyContent: "center",
            alignItems: "center",
            marginTop: "30px"
          }}
        >
          {this.props.a.a}
        </div>
      </div>
    );
  };
}

function App() {
  const [activeStep] = useState(0);
  const [a, setA] = useState({ a: 0 });

  // eslint-disable-next-line react/no-multi-comp

  function StepPage() {
    if (0 === 0) {
      return <MyComponnent a={a} setA={setA} />;
    } else {
      return <MyComponnent />;
    }
  }

  return (
    <div>
      <StepPage />
    </div>
  );
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
.App {
  font-family: sans-serif;
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<div id="root"></div>

2 个答案:

答案 0 :(得分:2)

问题在于,您正在通过在渲染函数中定义StepPage来创建组件的新实例

您可以重构StepPage组件,以便将其定义在render方法之外,

function StepPage({ setA, a}) {
  if (0 === 0) {
    return <MyComponnent a={a} setA={setA} />;
  } else {
    return <MyComponnent />;
  }
}

export default function App() {
  const [activeStep] = useState(0);
  const [a, setA] = useState({ a: 0 });

  return (
    <div>
      <StepPage a={a} setA={setA} />
    </div>
  );
}

答案 1 :(得分:2)

每次渲染StepPage时,重新定义示例中的

App

正常调用该函数而不是将其用作React组件可以缓解此问题:

return (
  <div>
    {StepPage()}
  </div>
);

const useState = React.useState;

class MyComponnent extends React.Component {
  intervalID = null;

  componentDidMount() {
    console.log("MOUNTING");
    this.intervalID = setInterval(() => {
      this.props.setA({ a: this.props.a.a + 1 });
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.intervalID);
  }

  render = () => {
    return (
      <div
        style={{
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          flexDirection: "column"
        }}
      >
        <div
          style={{
            flexDirection: "row",
            display: "flex",
            justifyContent: "center",
            alignItems: "center",
            marginTop: "30px"
          }}
        >
          {this.props.a.a}
        </div>
      </div>
    );
  };
}

function App() {
  const [activeStep] = useState(0);
  const [a, setA] = useState({ a: 0 });

  // eslint-disable-next-line react/no-multi-comp

  function StepPage() {
    if (0 === 0) {
      return <MyComponnent a={a} setA={setA} />;
    } else {
      return <MyComponnent />;
    }
  }

  return (
    <div>
      {StepPage()}
    </div>
  );
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
.App {
  font-family: sans-serif;
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<div id="root"></div>