React js zmienia stan komponentu potomnego z komponentu rodzica


100

Mam dwa komponenty: Komponent nadrzędny, z którego chcę zmienić stan komponentu podrzędnego:

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

I składnik podrzędny :

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

Muszę albo zmienić stan otwarcia składnika podrzędnego ze składnika nadrzędnego, albo wywołać toggleMenu () składnika podrzędnego w składniku nadrzędnym po kliknięciu przycisku w składniku nadrzędnym?


Może możesz mieć odniesienie do dziecka w rodzicu i wyraźnie zmienić stan dziecka, Zobacz ten dokument
— Chaojun Zhong

Odpowiedzi:


125

Stan powinien być zarządzany w komponencie nadrzędnym. Możesz przenieść openwartość do komponentu podrzędnego, dodając właściwość.

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

Czy można tego użyć do kontrolowania właściwości CSS, takiej jak „display”? tak jak w przypadku, jeśli mój atrybut „open” zawiera „none” lub „inline-block”, czy właściwość wyświetlania css zostanie zaktualizowana?
— deusofnull

3
Tak, to jest zasadniczo to, co robi pakiet react-classnames, ale pozwala też zawsze zastosować zestaw nazw klas i warunkowo zastosować inne. Na przykład: classNames({ foo: true, bar: this.props.open });// => 'foo', gdy this.props.open = false i 'foo bar', gdy this.props.open = true.
— deusofnull

1
Jak możemy zmienić stan otwarty w komponencie potomnym?
— Priyabrata Atha

1
możesz dodać właściwość toggledo ChildComponent <ChildComponent open={this.state.open} toggle={this.toggleChildMenu.bind(this)} />i wywołać this.props.toggle()komponent podrzędny
— Olivier Boissé

1
Nie rozumiem, możesz to wywołać w dowolnym miejscu w komponencie podrzędnym, gdy tylko określisz tę właściwość podczas deklarowania ChildComponent-><ChildComponent toggle={this.toggleChildMenu.bind(this)} />
— Olivier Boissé

25

Komponent nadrzędny może zarządzać stanem potomnym, przekazując właściwość dziecku, a dziecko konwertuje tę właściwość w stanie za pomocą componentWillReceiveProps.

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
w reakcji 16 użyj getDerivedStateFromProps
— Fadi Abo Msalam

1
@FadiAboMsalam Używam wersji React 16.7.0 z wersją @ Types / Reaguj 16.7.18. Przynajmniej po stronie TypeScript nie ma getDerivedStateFromProps(). Jednak odpowiedź Miguela sugerująca użycie componentWillReceiveProps(props)jest dostępna i zadziałała jak urok w moim środowisku.
— Manfred

W takim przypadku, w jaki sposób zmiana stanu toggleMenu () wewnątrz składnika podrzędnego dotarłaby do elementu nadrzędnego? Wyobraź sobie, że zamykam szufladę, skąd komponent nadrzędny wiedziałby, że został zamknięty?
— norman123123

20

Powyższa odpowiedź jest dla mnie częściowo poprawna, ale w moim scenariuszu chcę ustawić wartość na stan, ponieważ użyłem wartości do wyświetlenia / przełączenia modalu. Więc użyłem jak poniżej. Mam nadzieję, że to komuś pomoże.

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

Źródła - https://github.com/kriasoft/react-starter-kit/issues/909#issuecomment-252969542


2
To jest to, czego chcę, ale zastanawiam się, dlaczego nie używać po prostu reagowania? patrz dokumentacja
— Chaojun Zhong

Co robi rekwizyt onRef?
— norman123123

2

Możesz użyć createRef, aby zmienić stan komponentu podrzędnego z komponentu nadrzędnego. Oto wszystkie kroki.

  1. Utwórz metodę zmiany stanu w komponencie podrzędnym.

    2 - Utwórz odwołanie do komponentu podrzędnego w komponencie nadrzędnym za pomocą React.createRef ().

    3 - Dołącz odwołanie do komponentu podrzędnego za pomocą ref = {}.

    4 - Wywołaj metodę komponentu potomnego za pomocą this.yor-reference.current.method.

Komponent nadrzędny


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

Komponent podrzędny


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

Możesz wysłać właściwość od rodzica i użyć jej w komponencie potomnym, aby oprzeć zmiany stanu dziecka na przesłanych zmianach właściwości i możesz sobie z tym poradzić, używając getDerivedStateFromProps w komponencie potomnym.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.