如何从组件内部或外部更改值

问题描述 投票:0回答:1

我希望能够从组件内部和外部更改值。

下面是我的尝试副本,来自 https://codesandbox.io/p/sandbox/42xrs2

问题已在沙箱中自我记录,这是一份副本:

  • 如果在从内部更改之前完成,从外部更改是可行的
  • 一旦从内部改变,就不可能再从外部改变

App.js 文件:

import React, { useState } from "react";
import "./styles.css";
import TestParam from "./TestParam";

export default function App() {
  const [outsideChange, setOutsideChange] = useState(null);
  return (
    <div className="App">
      <button
        onClick={() => {
          setOutsideChange("");
          setOutsideChange("Changed from outside");
        }}
      >
        Change from the outside
      </button>
      <br />
      <br />
      <TestParam testStringProp={outsideChange} />
    </div>
  );
}

TestParam.js 文件:

import React, { useState, useEffect } from "react";

export default function TestParam({ testStringProp }) {
  const [testString, setTestString] = useState(testStringProp);
  useEffect(() => {
    setTestString(testStringProp);
    // alert("in useEffect");
  }, [testStringProp]);

  return (
    <>
      <button onClick={() => setTestString("changed from inside component")}>
        Change from inside
      </button>
      <h1>Result here: {testString}</h1>
      <p>Change from the ouside works if done before change from the inside</p>

      <p>
        Once changed from the inside, impossible to change again from the
        outside
      </p>
    </>
  );
}
reactjs react-hooks
1个回答
0
投票

外部状态实际上不会改变,因为 React 默认批量状态更新。当你打电话时

setOutsideChange("");
setOutsideChange("Changed from outside");

更新是组合的,也就是说状态没有被清除然后更新,并且看到当前和之前的状态是相同的,

testStringProp
的值实际上没有改变,并且
useEffect
没有被触发。

一个简单的解决方案是更改您设置的值。例如,将

setOutsideChange("Changed from outside")
替换为
setOutsideChange(Math.random())
,您应该会看到它正在更新。

如果需要静态文本,则需要用

flushSync
包裹每个设置的状态,因此每个状态都会导致重新渲染,首先清除状态,然后设置文本。

const { useState, useEffect } = React;
const { flushSync, createRoot } = ReactDOM;

function App() {
  const [outsideChange, setOutsideChange] = useState(null);
  return (
    <div className="App">
      <button
        onClick={() => {
          flushSync(() => setOutsideChange(""));
          flushSync(() => setOutsideChange("Changed from outside"));
        }}
      >
        Change from the outside
      </button>
      <br />
      <br />
      <TestParam testStringProp={outsideChange} />
    </div>
  );
}

function TestParam({ testStringProp }) {
  const [testString, setTestString] = useState(testStringProp);
  useEffect(() => {
    setTestString(testStringProp);
    // alert("in useEffect");
  }, [testStringProp]);

  return (
    <>
      <button onClick={() => setTestString("changed from inside component")}>
        Change from inside
      </button>
      <h1>Result here: {testString}</h1>
      <p>Change from the ouside works if done before change from the inside</p>

      <p>
        Once changed from the inside, impossible to change again from the
        outside
      </p>
    </>
  );
}

createRoot(root).render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>

<div id="root"></div>

© www.soinside.com 2019 - 2024. All rights reserved.