【问题标题】:Get consolidated data from all the child components in the form of an object inside a parent component : React JS以父组件内的对象形式从所有子组件获取合并数据:React JS
【发布时间】:2019-12-24 01:05:13
【问题描述】:

我正在为一个应用程序实现一个设置页面。对于每个设置,我都实现了一个启用(绿色)或禁用(红色)状态的滑块。但是父级的设置是只读的,并且是根据其子级的值计算的。

Parent 的设置推导如下:如果所有孩子都是红色的,则父母保持红色;如果都是绿色,则父母保持绿色;如果至少有一个孩子是绿色的,那么父母会保持灰色(待定)。

这些设置按如下方式分组:

父功能 1:(只读切换)

 Setting 1   (Toggle)

 Setting 2   (Toggle)

父功能 2:(只读切换)

Setting 1   (Toggle)

Setting 2   (Toggle)

最后还有一个按钮,它为我提供了所有父母和孩子的综合价值观。但到目前为止,我只能和一个父母和两个孩子一起做。

有人可以帮助在一个地方获取所有设置的合并值(就像配置所有这些设置的超级父组件)。

为此,我将 react-multi-toggle 用于此切换开关。

非常感谢您的帮助。

代码沙盒:https://codesandbox.io/s/react-multi-toggle-solution-perfect-v9bi5

应用


import React from "react";
import ChildSwitch from "./ChildSwitch";
import ParentSwitch from "./ParentSwitch";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      parentVal: "disabled",
      switch1Val: "enabled",
      switch2Val: "disabled"
    };
  }

  componentDidMount() {
    this.setParentSwitchValue();
  }

  onGetChildSwitchValues = () => {
    console.log(this.state);
  };

  setChildSwitchValue = (whichSwitch, selected) => {
    this.setState(
      prevState => ({ ...prevState, [whichSwitch]: selected }),
      this.setParentSwitchValue
    );
  };

  setParentSwitchValue = () => {
    const { switch1Val, switch2Val } = this.state;
    const switchStates = [switch1Val, switch2Val];
    let parent = "pending";
    if (switchStates.every(val => val === "enabled")) {
      parent = "enabled";
    }
    if (switchStates.every(val => val === "disabled")) {
      parent = "disabled";
    }
    this.setState(prevState => ({ ...prevState, parentVal: parent }));
  };

  render() {
    const { parentVal, switch1Val, switch2Val } = this.state;
    return (
      <>
        <div className="boxed">
          Parent Setting 1 :{" "}
          <ParentSwitch
            parentSwitch={parentVal}
            onSelect={this.setParentSwitchValue}
          />
          Setting 1:
          <ChildSwitch
            switchName={"switch1Val"}
            selected={switch1Val}
            onSelect={this.setChildSwitchValue}
          />
          Setting 2:
          <ChildSwitch
            switchName={"switch2Val"}
            selected={switch2Val}
            onSelect={this.setChildSwitchValue}
          />
        </div>
        <button onClick={this.onGetChildSwitchValues}>Get All Values</button>
      </>
    );
  }
}

儿童设置


import MultiToggle from "react-multi-toggle";
import React from "react";

export default class ChildSwitch extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      options: [
        {
          displayName: "Disabled",
          value: "disabled"
        },
        {
          displayName: "Enabled",
          value: "enabled"
        }
      ]
    };
  }

  onSelectOption = selected => {
    this.props.onSelect(this.props.switchName, selected);
  };

  render() {
    const { options } = this.state;
    const { selected } = this.props;
    return (
      <MultiToggle
        options={options}
        selectedOption={selected}
        onSelectOption={this.onSelectOption}
      />
    );
  }
}

家长设置


import MultiToggle from "react-multi-toggle";
import React from "react";
import "react-multi-toggle/style.css";

export default class ParentSwitch extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      options: [
        {
          displayName: "Disabled",
          value: "disabled"
        },
        {
          displayName: "Pending",
          value: "pending"
        },
        {
          displayName: "Enabled",
          value: "enabled"
        }
      ]
    };
  }

  render() {
    const { options } = this.state;
    return (
      <MultiToggle
        options={options}
        selectedOption={this.props.parentSwitch}
        onSelectOption={() => {}}
      />
    );
  }
}



【问题讨论】:

    标签: javascript reactjs ecmascript-6 react-hooks setstate


    【解决方案1】:

    我建议您将您的孩子和父母归为一个组件。假设我们将其命名为Settings。然后,我们创建另一个组件来呈现设置列表和一个按钮。最后一个组件将保存所有设置的值。最后,每次Setting Component Change 的值,我们都会更新列表。查看示例working app here

    应用组件

    export default class App extends PureComponent {
      state = {};
    
      onSettingChange = (settingId, setting) => {
        this.setState(prevState => ({
          ...prevState,
          [settingId]: setting
        }));
      };
    
      onGetSettingValues = () => {
        console.log(this.state);
      };
    
      render() {
        return (
          <Fragment>
            <Setting id="setting1" onChange={this.onSettingChange} />
            <Setting id="setting2" onChange={this.onSettingChange} />
            <button onClick={this.onGetSettingValues}>Get All Values</button>
          </Fragment>
        );
      }
    }
    

    设置组件

    import React, { PureComponent, Fragment } from "react";
    import ChildSwitch from "./ChildSwitch";
    import ParentSwitch from "./ParentSwitch";
    
    export default class Setting extends PureComponent {
      state = {
        parentVal: "disabled",
        switch1Val: "enabled",
        switch2Val: "disabled"
      };
    
      componentDidMount() {
        this.setParentSwitchValue();
      }
    
      setChildSwitchValue = (whichSwitch, selected) => {
        this.setState(
          prevState => ({ ...prevState, [whichSwitch]: selected }),
          this.setParentSwitchValue
        );
      };
    
      handleChange = () => {
        const { id, onChange } = this.props;
        onChange(id, this.state);
      };
    
      setParentSwitchValue = () => {
        const { switch1Val, switch2Val } = this.state;
        const switchStates = [switch1Val, switch2Val];
        let parent = "pending";
        if (switchStates.every(val => val === "enabled")) {
          parent = "enabled";
        }
        if (switchStates.every(val => val === "disabled")) {
          parent = "disabled";
        }
    
        this.setState(
          prevState => ({ ...prevState, parentVal: parent }),
          this.handleChange
        );
      };
    
      render() {
        const { parentVal, switch1Val, switch2Val } = this.state;
        return (
          <Fragment>
            <div className="boxed">
              Parent Setting 1
              <ParentSwitch
                parentSwitch={parentVal}
                onSelect={this.setParentSwitchValue}
              />
              Setting 1:
              <ChildSwitch
                switchName={"switch1Val"}
                selected={switch1Val}
                onSelect={this.setChildSwitchValue}
              />
              Setting 2:
              <ChildSwitch
                switchName={"switch2Val"}
                selected={switch2Val}
                onSelect={this.setChildSwitchValue}
              />
            </div>
          </Fragment>
        );
      }
    }
    

    【讨论】:

    • 现在如果我必须从 API 中获取所有这些开关的值,该 API 调用应该写在哪里?
    • 您可以在 App Component 上实现 componentDidMount 并在那里获取您的开关值。
    • 是的,您需要 Setting Componet Sate 的初始值作为您从 API 获取的值。
    【解决方案2】:

    将所有状态放入一个 context hook

    const SettingsContext = createContext({state1, state2/* all your states in here*/);
    

    然后,您将把整个事情包装到这个上下文中:

    <SettingsContext.Provider>
      <App/>
    </SettingsContext.Provider>
    

    现在您可以访问任何孩子、父母等的状态。但我建议不要将“禁用”、“启用”等内容存储为字符串,而是将状态存储为 { enabled: true, pending: false}

    【讨论】:

    • sn-p 在这里真的很有用:) 可能是我的沙盒分叉
    猜你喜欢
    • 2020-08-14
    • 2023-03-25
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-05
    • 1970-01-01
    相关资源
    最近更新 更多