2017-02-21 62 views
1

Я хотел бы создать компонент Dropdown.Как разделяемое состояние между отдельным компонентом в React JS?

Когда я нажимаю на DropdownHandler компонента, я хотел бы сохранить состояние isOpen которое может быть true или false. Если true, то этот state используется <DropdownContent/>, чтобы отобразить содержание. И по умолчанию stateisOpen является false в <Dropdown /> Компонент

Как я могу это сделать?

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

} 
+0

Вы можете использовать [Redux] (https://github.com/reactjs/react-redux) для этого. – Andrew

+0

Прочитайте [Подъемное состояние вверх] (https://facebook.github.io/react/docs/lifting-state-up.html) и [Мышление в реале] (https://facebook.github.io/react/docs /thinking-in-react.html) - они объясняют идиоматический способ разделения государства. –

ответ

1

Я нашел решение, основанное на ответах @ Андрей. Не уверен, что это правильно. Но он решает общее состояние, но используется только 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> 
     ); 
    } 

} 
+1

Всегда объявляйте реквизиты в компоненте. И вы можете удалить свой конструктор и объявить свой прямо в компоненте (посмотрите на мой ответ). – Kornflexx

1

Если вы не хотите использовать Redux. Вы устанавливаете и управляете своим статусом дочернего компонента opend и устанавливаете его в DropdownContent с реквизитами. Поэтому, когда вы измените opend, щелкнув 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; 
+0

Да! Очень быстрый ответ! Спасибо. Это может быть работа, я вижу. Но какие компоненты 'Dropdown, DropdownHandler, DropdownContent' используются, если эти состояния отсутствуют? Потому что я хотел бы использовать этот компонент «Dropdown» где угодно. не только в 'HeaderConnected' – Steffi

+0

Я думаю, вам нужно выпустить раскрывающийся список компонентов для повторного использования, что-то вроде вашего компонента HeaderConnected. И отправьте туда контент с реквизитом. – Andrew

+0

Да, я хотел бы сделать что-то вроде этого, но как отправить туда контент с реквизитом и сохранить состояние в компоненте выпадающего списка? – Steffi

0

Вы можете изменить имя обратного вызова «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> 
     ); 
    } 

} 
+0

Я не понимаю этого решения :( – Steffi

+0

Выпадающий компонент будет содержать dropdownhandler и dropdowncontent. Он дает им открытое состояние по реквизитам, они могут вызывать onOpen реквизиты, чтобы изменить значение open. Я предположил, что ваш компонент обработчика вызовет этот обратный вызов (onOpen) – Kornflexx

+0

Я понимаю сейчас. Что вы думаете о решении, которое я разместил? Я не уверен. – Steffi