React JS 中不同组件之间如何共享状态?

How shared state between separate component in React JS?

我想创建下拉组件。

当我点击DropdownHandler组件时,我想保存状态isOpen,可以是truefalse。如果 true<DropdownContent/> 使用相同的 state 来显示内容。默认情况下,state isOpen<Dropdown /> 组件

中的 false

请问我该怎么做?

App.jsx

import React from 'react';
import {Dropdown, DropdownHandler, DropdownContent} from '../../components/Dropdown/Dropdown.jsx';

class HeaderConnected extends React.Component {

    constructor(props) {
        super(props);
    }

    render() {
        return (
            <div>
              <Dropdown>
                 <DropdownHandler>
                     <Avatar title="Roberto"></Avatar>
                 </DropdownHandler>
                 <DropdownContent>
                     <li>Menu</li>
                     <li>Settings</li>
                 </DropdownContent>
               </Dropdown>
            </div>
        );
    }

}

export default HeaderConnected;

Dropdown.jsx

export class Dropdown extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            opened: false
        }
    }

    render() {

        return (
            <div className="DROPDOWN">
                {this.props.children}
            </div>
        );
    }

}

export class DropdownHandler extends React.Component {

    constructor(props) {
        super(props);
    }

    render() {

        return (
            <div className="DROPDOWN__HANDLER">
                {this.props.children}
            </div>
        );
    }

}

export class DropdownContent extends React.Component {

    constructor(props) {
        super(props);
    }

    render() {

        return (
            <div className="DROPDOWN__CONTENT">
                {this.props.children}
            </div>
        );
    }

}

如果你不想使用 redux。 您设置和控制子组件的 opend 状态,并使用道具将其设置为 DropdownContent。因此,当您通过单击 DropdownHandler 更改打开时,您的 DropdownContent 将收到新的提示并调用重新渲染。

import React from 'react';
import {Dropdown, DropdownHandler, DropdownContent} from '../../components/Dropdown/Dropdown.jsx';

class HeaderConnected extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            opened: false
        }
    }
    onClick(){
       let condition = this.state.opened;
       this.setState({opened: !condition });
    }
    render() {
        return (
            <div>
              <Dropdown>
                 <DropdownHandler onClick={this.onClick.bind(this)}>
                     <Avatar title="Roberto"></Avatar>
                 </DropdownHandler>
                 <DropdownContent opened={this.state.opened}>
                     <li>Menu</li>
                     <li>Settings</li>
                 </DropdownContent>
               </Dropdown>
            </div>
        );
    }

}

export default HeaderConnected;

随意更改回调的名称"onOpen"

export class Dropdown extends React.Component {

    state = {
        open: false
    }

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

    render() {

        return (
            <div className="DROPDOWN">
                {React.cloneElement(this.props.children, { open: this.state.open, onOpen: this.handleOpen })}
            </div>
        );
    }

}

export class DropdownHandler extends React.Component {

    static propTypes = {
      open: React.PropTypes.bool.isRequired,
      onOpen: React.PropTypes.func.isRequired
    }

    render() {

        return (
            <div className="DROPDOWN__HANDLER" onClick={this.props.onOpen}>
                {this.props.children}
            </div>
        );
    }

}

export class DropdownContent extends React.Component {

    static propTypes = {
      open: React.PropTypes.bool.isRequired,
      onOpen: React.PropTypes.func.isRequired
    }

    render() {
        // handle visibility here
        return (
            <div className="DROPDOWN__CONTENT">
                {this.props.children}
            </div>
        );
    }

}

我根据@Andrew 的回答找到了解决方案。不确定这是否正确。但它解决了共享状态,仅供Dropdown使用。我通过道具

传递处理程序和内容

你怎么看?

App.jsx

import React from 'react';
import {Dropdown} from '../../components/Dropdown/Dropdown.jsx';

class HeaderConnected extends React.Component {

    constructor(props) {
        super(props);
    }

    render() {
        return (
            <div>
              <Dropdown handler={<Avatar title="Roberto" />}>
                  <li>Menu</li>
                  <li>Settings</li>
              </Dropdown>
            </div>
        );
    }

}

export default HeaderConnected;

Dropdown.jsx

export class Dropdown extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            opened: false
        }
    }

    render() {

        return (
            <div className="DROPDOWN">
               <div className="DROPDOWN_HANDLER" onClick="...">
                   {this.props.handler}
               </div>
               <div className="DROPDOWN_CONTENT">
                   {this.props.children}
               </div>
            </div>
        );
    }

}