繁体   English   中英

为什么将更新的 state 从子组件提升到父组件不起作用?

[英]Why lifting an updated state from a child to a parent component does not work?

在切换孩子的 state 后尝试更新父组件的 UI 时,我设法达到了我想要的结果,但是,作为 React 初学者,我想我做得不太对。

正如您将在下面的代码中看到的,我根据event.target.value更新了单选按钮组件的 state,然后通过onToggle道具使用SitePageToggle ( WebsitePicker ) 将其提升到组件。 问题是,根据我的理解,我应该使用selectedRadioBtn及其更新的 state。但是,当我通过selectedRadioBtn以便我可以根据它来确定我的QAObject变量的 state 时,“网站”和“页面”之间的切换顺序' 被搞砸了和颠倒了。 如果我在子组件本身中使用更新的 state,这不是问题。

我知道[状态更新可能是异步的][1],但是通过接受回调使用 useState 钩子第二个版本也没有解决问题。

这是父组件中的代码:

import styles from "./WebsitePicker.module.css";
import { useState } from "react";
import SitePageToggle from "./SitePageToggle";
import SubmitButton from "./Buttons/SubmitButton";

function WebsitePicker() {
    const [QAObject, setQAObject] = useState("Website");
    const { label, input__url } = styles;

    const toggleWebsitePageHandler = toggleData => {
        if (toggleData === 'Website') {
            setQAObject("Website");
        } else {
            setQAObject("Page");
        }
    };

    return (
        <>
            <SitePageToggle onToggle={toggleWebsitePageHandler} />
            <form onSubmit={formSubmissionHandler}>
                <label className={label} htmlFor="picker">
                    Enter the URL of the {QAObject} you wish to QA.
                </label>
                <br />
                <input
                    id="picker"
                    type="url"
                    className={input__url}
                />
                <SubmitButton>QA my page</SubmitButton>
            </form>
        </>
    );
}

export default WebsitePicker;

这是子组件中的代码:

import RadioButton from "./Buttons/RadioButton";

function SitePageToggle({ onToggle }) {
    const [selectedRadioBtn, setSelectedRadioBtn] = useState("Website");

    const isRadioSelected = (btnValue) => selectedRadioBtn === btnValue;

    const handleToggle = event => {
        setSelectedRadioBtn(event.target.value);
        onToggle(event.target.value);
    };

return (
    <ul>
        <li>
            <RadioButton
                label="Website"
                name="react-radio-btn"
                value="Website"
                checked={isRadioSelected("Website")}
                onChange={handleToggle}
            />
        </li>
        <li>
            <RadioButton
                label="Page"
                name="react-radio-btn"
                value="Page"
                checked={isRadioSelected("Page")}
                onChange={handleToggle}
            />
        </li>
    </ul>
);
}

export default SitePageToggle;


  [1]: https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

不确定我是否完全理解用例,但如果目标是将selectedRadioBtn state提升到父级(而不是同步两个状态),那么SitePageToggle可能不需要保留 state 的单独副本,而是从父母。

快速简化演示: stackblitz

WebsitePicker QAObject作为selectedRadioBtn传递:

<SitePageToggle
  selectedRadioBtn={QAObject}
  onToggle={toggleWebsitePageHandler}
/>

SitePageToggle ,使用道具中的selectedRadioBtn作为 state:

import RadioButton from "./Buttons/RadioButton";

function SitePageToggle({ selectedRadioBtn, onToggle }) {
  const isRadioSelected = (btnValue) => selectedRadioBtn === btnValue;
  const handleToggle = (event) => {
    onToggle(event.target.value);
  };

  return (
    <ul>
      <li>
        <RadioButton
          label="Website"
          name="react-radio-btn"
          value="Website"
          checked={isRadioSelected("Website")}
          onChange={handleToggle}
        />
      </li>
      <li>
        <RadioButton
          label="Page"
          name="react-radio-btn"
          value="Page"
          checked={isRadioSelected("Page")}
          onChange={handleToggle}
        />
      </li>
    </ul>
  );
}

export default SitePageToggle;

要正确传递子项 state selectedRadioBtn ,您应该使用 useEffect()。 useEffect 的第二个参数是依赖数组,所以只要selectedRadioBtn发生变化,它就会触发。

import RadioButton from "./Buttons/RadioButton";

function SitePageToggle({ onToggle }) {
    const [selectedRadioBtn, setSelectedRadioBtn] = useState("Website");

    const isRadioSelected = (btnValue) => selectedRadioBtn === btnValue;

    const handleToggle = event => {
        setSelectedRadioBtn(event.target.value);
        // onToggle(event.target.value); <-- delete this here
    };

    useEffect(() => {
        onToggle(selectedRadioBtn);
    }, [selectedRadioBtn]);

    return (
        <>...</>
    );
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM