Я пытаюсь реализовать страницу настроек, где у меня есть общие настройки и какие-то дочерние настройки (в виде слайдера).

Я не могу установить инициал, который передается от родителя.

Я занимаюсь следующими сценариями:

1) Когда все дочерние настройки включены, родительское состояние переключения должно быть включено.

2) Когда какая-либо из дочерних настроек отключена, тогда родители должны переключиться в состояние ожидания

3) Когда все дочерние настройки выключены, родительское состояние должно быть выключено.

4) Также по нажатию кнопки мне нужно получить текущее состояние всех дочерних компонентов.

Если добавить setState внутри componentDidMount внутри parent (может быть, вызов API будет записан внутри него, так что начальные состояния переключателей будут установлены соответствующим образом, а затем будут иметь возможность изменять), дочерние переключатели должны иметь возможность получить значение состояния верно, но здесь этого нет.

И я также вижу, что переключение происходит неправильно. Здесь это происходит, когда вы нажимаете на уже выбранную, что в идеале неправильно

Опробовал следующий подход, но это не похоже на работу. Для этого я использую реагирующее мульти-переключение для этого переключателя.

Может здесь кто-нибудь помочь?

Ссылка песочницы кода: https://codesandbox.io/s/react-multi- тумблер решение - yn3fh

Приложение

import React from "react";
import ReactDOM from "react-dom";
import ChildSwitch from "./ChildSwitch";
import ParentSwitch from "./ParentSwitch";
import "./styles.css";

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

  componentDidMount() {
    this.setState({
      switch1Val: "enabled",
      switch2Val: "disabled",
      switch3Val: "enabled"
    });
  }

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

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

  setParentSwitchValue = () => {
    const { switch1Val, switch2Val, switch3Val } = this.state;
    const switchStates = [switch1Val, switch2Val, switch3Val];
    const parent = switchStates.every(this.isEnabled)
      ? "enabled"
      : switchStates.every(this.isDisabled)
      ? "disabled"
      : "pending";
    this.setState({ parentVal: parent });
  };

  isEnabled(value) {
    return value === "enabled";
  }

  isDisabled(value) {
    return value === "disabled";
  }

  render() {
    const { parentVal, switch1Val, switch2Val, switch3Val } = this.state;
    return (
      <>
        Parent Switch :{" "}
        <ParentSwitch
          parentSwitch={parentVal}
          onSelect={this.setParentSwitchValue}
        />
        Child Switches :
        <ChildSwitch
          childSwitch={switch1Val}
          switchName={"switch1Val"}
          onSelect={this.setChildSwitchValue}
        />
        <ChildSwitch
          childSwitch={switch2Val}
          switchName={"switch2Val"}
          onSelect={this.setChildSwitchValue}
        />
        <ChildSwitch
          childSwitch={switch3Val}
          switchName={"switch3Val"}
          onSelect={this.setChildSwitchValue}
        />
        <button onClick={this.onGetChildSwitchValues}>Get Child Values</button>
      </>
    );
  }
}

Родитель

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

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

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

export default ParentSwitch;

Ребенок

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",
          optionClass: "red"
        },
        {
          displayName: "Enabled",
          value: "enabled",
          optionClass: "green"
        }
      ],
      selected: ""
    };
  }

  componentDidMount() {
    this.setState({ selected: this.props.childSwitch });
  }

  onSelectOption = selected => {
    if (selected === "disabled") {
      this.setState({ selected: "enabled" }, () =>
        this.props.onSelect(this.props.switchName, "enabled")
      );
    } else {
      this.setState({ selected: "disabled" }, () =>
        this.props.onSelect(this.props.switchName, "disabled")
      );
    }
  };

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

1
joy08 17 Авг 2019 в 12:48

2 ответа

Лучший ответ

Чтобы решить эту проблему, нужно управлять родительскими и дочерними переключателями из главного компонента. Ознакомьтесь с рабочими раздвоенными кодами и ящиком

< Сильный > APP

import React from "react";
import ReactDOM from "react-dom";
import ChildSwitch from "./ChildSwitch";
import ParentSwitch from "./ParentSwitch";
import "./styles.css";

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

  componentDidMount() {
    this.setParentSwitchValue();
  }

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

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

  setParentSwitchValue = () => {
    const { switch1Val, switch2Val, switch3Val } = this.state;
    const switchStates = [switch1Val, switch2Val, switch3Val];
    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, switch3Val } = this.state;
    return (
      <>
        Parent Switch :{" "}
        <ParentSwitch
          parentSwitch={parentVal}
          onSelect={this.setParentSwitchValue}
        />
        Child Switches :
        <ChildSwitch
          switchName={"switch1Val"}
          selected={switch1Val}
          onSelect={this.setChildSwitchValue}
        />
        <ChildSwitch
          switchName={"switch2Val"}
          selected={switch2Val}
          onSelect={this.setChildSwitchValue}
        />
        <ChildSwitch
          switchName={"switch3Val"}
          selected={switch3Val}
          onSelect={this.setChildSwitchValue}
        />
        <button onClick={this.onGetChildSwitchValues}>Get Child Values</button>
      </>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Родитель

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

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

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

export default ParentSwitch;

Ребенок

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

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

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

export default ParentSwitch;
3
Morlo Mbakop 17 Авг 2019 в 11:00

Проблема в том, что вы не обновляете локальное состояние при изменении свойства childSwitch. Так что он останется в отключенном состоянии. Для этого вам нужно добавить метод componentDidUpdate или просто напрямую использовать свойство без какого-либо локального состояния.

В ChildSwitch

  componentDidUpdate(prevProps) {
    if(prevProps.childSwitch !== this.props.childSwitch) {
      this.setState({ selected: this.props.childSwitch });
    }
  }

Рабочая вилка: https://codesandbox.io/s/react-multi-toggle -решение - 8xnf3

1
Auskennfuchs 17 Авг 2019 в 10:04