最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - How to change value from either inside or outside a component - Stack Overflow

programmeradmin1浏览0评论

I want to be able to change a value from both inside and outside a component.

Below is a copy of my attempt, from

The problem is self documented in the sandbox, here is a copy:

  • Change from the ouside works if done before change from the inside
  • Once changed from the inside, impossible to change again from the outside

App.js file:

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 file:

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

I want to be able to change a value from both inside and outside a component.

Below is a copy of my attempt, from https://codesandbox.io/p/sandbox/42xrs2

The problem is self documented in the sandbox, here is a copy:

  • Change from the ouside works if done before change from the inside
  • Once changed from the inside, impossible to change again from the outside

App.js file:

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 file:

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>
    </>
  );
}
Share Improve this question edited Nov 20, 2024 at 11:21 DarkBee 15.6k8 gold badges72 silver badges117 bronze badges asked Nov 20, 2024 at 11:19 FrancisFrancis 8571 gold badge9 silver badges21 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

The outside state doesn't actually change because React batches state updates by defaults. When you call

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

the updates are combined, which means that the state isn't cleared and then updated, and see the current and previous states are identical, the value of testStringProp doesn't actually change, and the useEffect is not triggered.

A simple solution would be to change the value you set. For example, replace setOutsideChange("Changed from outside") with setOutsideChange(Math.random()), and you should see it's updating.

If you need static text, you'll need to wrap each set state with flushSync, so each of them would cause a re-render, first clearing the state, and then setting the text.

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/ajax/libs/react/18.3.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>

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

发布评论

评论列表(0)

  1. 暂无评论