React js змінює стан дочірнього компонента з батьківського


99

У мене є два компоненти: батьківський компонент, з якого я хочу змінити стан дочірнього компонента:

class ParentComponent extends Component {
  toggleChildMenu() {
    ?????????
  }
  render() {
    return (
      <div>
        <button onClick={toggleChildMenu.bind(this)}>
          Toggle Menu from Parent
        </button>
        <ChildComponent />
      </div>
    );
  }
}

І дочірній компонент :

class ChildComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      open: false;
    }
  }

  toggleMenu() {
    this.setState({
      open: !this.state.open
    });
  }

  render() {
    return (
      <Drawer open={this.state.open}/>
    );
  }
}

Мені потрібно або змінити стан відкритого дочірнього компонента з батьківського компонента, або викликати дочірній компонент toggleMenu () з батьківського компонента, коли натискається кнопка в батьківському компоненті?


Можливо, ви можете мати дочірню довідку у батьків і явно змінити стан дитини, див. Цей документ
Chaojun Zhong

Відповіді:


124

Керувати станом слід у батьківському компоненті. Ви можете передати openзначення дочірньому компоненту, додавши властивість.

class ParentComponent extends Component {
   constructor(props) {
      super(props);
      this.state = {
        open: false
      };

      this.toggleChildMenu = this.toggleChildMenu.bind(this);
   }

   toggleChildMenu() {
      this.setState(state => ({
        open: !state.open
      }));
   }

   render() {
      return (
         <div>
           <button onClick={this.toggleChildMenu}>
              Toggle Menu from Parent
           </button>
           <ChildComponent open={this.state.open} />
         </div>
       );
    }
}

class ChildComponent extends Component {
    render() {
      return (
         <Drawer open={this.props.open}/>
      );
    }
}

Чи можна це використовувати для управління властивістю css, як-от 'display'? як і в тому випадку, якщо мій проп «відкритий» містить або «немає», або «вбудований блок», чи буде оновлено css display prop?
deusofnull

3
Так, це по суті те, що робить пакет реакцій-класів імен, але він також дозволяє завжди застосовувати набір імен класів та умовно застосовувати інші. classNames({ foo: true, bar: this.props.open });Ось так : // => 'foo', коли this.props.open = false і 'foo bar', коли this.props.open = true.
deusofnull

1
Як ми можемо змінити стан відкритості в дочірньому компоненті?
Priyabrata Atha

1
ви можете додати властивість toggleдо ChildComponent <ChildComponent open={this.state.open} toggle={this.toggleChildMenu.bind(this)} />і викликати this.props.toggle()дочірній компонент
Olivier Boissé 02

1
Я не розумію, ви можете зателефонувати куди завгодно в дочірній компонент, як тільки ви вказали цю властивість при оголошенні ChildComponent-><ChildComponent toggle={this.toggleChildMenu.bind(this)} />
Олів'є Буассе

25

Батьківський компонент може керувати дочірнім станом, передаючи властивість дочірньому, і дочірній матеріал перетворює цей опис у стан за допомогою компонентаWillReceiveProps.

class ParentComponent extends Component {
  state = { drawerOpen: false }
  toggleChildMenu = () => {
    this.setState({ drawerOpen: !this.state.drawerOpen })
  }
  render() {
    return (
      <div>
        <button onClick={this.toggleChildMenu}>Toggle Menu from Parent</button>
        <ChildComponent drawerOpen={this.state.drawerOpen} />
      </div>
    )
  }
}

class ChildComponent extends Component {
  constructor(props) {
    super(props)
    this.state = {
      open: false
    }
  }

  componentWillReceiveProps(props) {
    this.setState({ open: props.drawerOpen })
  }

  toggleMenu() {
    this.setState({
      open: !this.state.open
    })
  }

  render() {
    return <Drawer open={this.state.open} />
  }
}

1
в реакції 16 використовувати getDerivedStateFromProps
Фаді Або Мсалам

1
@FadiAboMsalam Я використовую React версію 16.7.0 з версією @ Types / React 16.7.18. Принаймні, на стороні TypeScript, здається, цього немає getDerivedStateFromProps(). Однак відповідь Мігеля, що пропонує використовувати, componentWillReceiveProps(props)є доступною і в моєму оточенні спрацювала як шарм.
Манфред

У цьому випадку, як зміниться стан toggleMenu () всередині дочірнього компонента, який потрапить до батьківського? Уявіть, я закриваю шухляду, звідки батьківський компонент знає, що він закритий?
norman123123

20

Наведена вище відповідь для мене частково правильна, але в моєму сценарії я хочу встановити значення в стан, оскільки я використовував значення для показу / перемикання модального режиму. Тож я використав, як нижче. Сподіваюся, це комусь допоможе.

class Child extends React.Component {
  state = {
    visible:false
  };

  handleCancel = (e) => {
      e.preventDefault();
      this.setState({ visible: false });
  };

  componentDidMount() {
    this.props.onRef(this)
  }

  componentWillUnmount() {
    this.props.onRef(undefined)
  }

  method() {
    this.setState({ visible: true });
  }

  render() {
    return (<Modal title="My title?" visible={this.state.visible} onCancel={this.handleCancel}>
      {"Content"}
    </Modal>)
  }
}

class Parent extends React.Component {
  onClick = () => {
    this.child.method() // do stuff
  }
  render() {
    return (
      <div>
        <Child onRef={ref => (this.child = ref)} />
        <button onClick={this.onClick}>Child.method()</button>
      </div>
    );
  }
}

Довідка - https://github.com/kriasoft/react-starter-kit/issues/909#issuecomment-252969542


2
Це те, що я хочу, але мені цікаво, чому б просто не використовувати реакційні посилання? див. документ
Chaojun Zhong

Що робить опис onRef?
norman123123

2

Ви можете використовувати createRef, щоб змінити стан дочірнього компонента з батьківського. Ось усі кроки.

  1. Створіть метод зміни стану дочірнього компонента.

    2 - Створіть посилання на дочірній компонент у батьківському компоненті за допомогою React.createRef ().

    3 - Прикріпіть посилання на дочірній компонент за допомогою ref = {}.

    4 - Виклик методу дочірнього компонента за допомогою this.yor-reference.current.method.

Батьківський компонент


class ParentComponent extends Component {
constructor()
{
this.changeChild=React.createRef()
}
  render() {
    return (
      <div>
        <button onClick={this.changeChild.current.toggleMenu()}>
          Toggle Menu from Parent
        </button>
        <ChildComponent ref={this.changeChild} />
      </div>
    );
  }
}

Дочірній компонент


class ChildComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      open: false;
    }
  }

  toggleMenu=() => {
    this.setState({
      open: !this.state.open
    });
  }

  render() {
    return (
      <Drawer open={this.state.open}/>
    );
  }
}




1

Ви можете надіслати проп від батьків і використовувати його в дочірньому компоненті, щоб змінити стан дитини на основі надісланих змін проп, і ви можете впоратися з цим, використовуючи getDerivedStateFromProps у дочірньому компоненті.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.