通过单击另一个组件中呈现的元素来打开<modal>

时间:2018-06-26 14:36:14

标签: reactjs semantic-ui-react

我正在使用一组语义UI <Item>组件列出一堆产品。我希望能够在单击<Item>时编辑产品的详细信息,并且我认为实现这一目标的最佳方法是使用<Modal>组件。

我希望将所有内容分解为可重用的组件。

(注意:我故意省略了一些import语句,以使内容易于阅读。)

App.js

import { ProductList } from 'components';

const App = () => (
  <Segment>
    <Item.Group divided>
      <ProductList/>
    </Item.Group>
  </Segment>
)

export default App;

components / ProductList.js

import { ProductListItem } from '../ProductListItem';

export default class ProductList extends Component {
  constructor() {
    super()
    this.state = { contents: [] }
  }

  componentDidMount() {
    var myRequest = new Request('http://localhost:3000/contents.json');
    let contents = [];

    fetch(myRequest)
    .then(response => response.json())
    .then(data => {
      this.setState({ contents: data.contents });
    });

    this.setState({ contents: contents });
  }

  render() {
    return (
      this.state.contents.map(content => {
        return (
          <ProductListItem
            prod_id={content.prod_id}
            prod_description={content.prod_description}
            category_description={content.category_description}
          />
        );
      })
    )
  }
}

components / ProductListItem.js

export default class ProductListItem extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <Item key={`product-${this.props.prod_id}`} as='a'>
        <Item.Content>
          <Item.Header>{this.props.prod_description}</Item.Header>
          <Item.Description>
            <p>{this.props.prod_description}</p>
          </Item.Description>
        </Item.Content>
      </Item>
    )
  }
}

所有这些都能很好地工作,并且产品列表会按预期显示。

我还使用Modal docs中的示例之一创建了一个基本的模态组件:

components / ModalExampleControlled.js

export default class ModalExampleControlled extends Component {
  state = { modalOpen: false }

  handleOpen = () => this.setState({ modalOpen: true })
  handleClose = () => this.setState({ modalOpen: false })

  render() {
    return (
      <Modal
        trigger={<Button onClick={this.handleOpen}>Show Modal</Button>}
        open={this.state.modalOpen}
        onClose={this.handleClose}
        size='small'
      >
        <Header icon='browser' content='Cookies policy' />
        <Modal.Content>
          <h3>This website uses cookies etc ...</h3>
        </Modal.Content>
        <Modal.Actions>
          <Button color='green' onClick={this.handleClose}>Got it</Button>
        </Modal.Actions>
      </Modal>
    )
  }
}

因此,这将创建一个在呈现<ModalExampleControlled />的任何地方都显示将其读取的按钮,并且该按钮会导致模态出现-很好。

当单击产品列表中的<Item>元素之一(从而摆脱按钮)时,如何显示模态?

非常感谢您的时间。

克里斯

1 个答案:

答案 0 :(得分:1)

您的问题是当前模态在内部管理自己的状态。只要是这种情况,并且其他任何组件都无法访问该状态,则无法从外部触发模式组件。

有多种解决方法。最好的方法取决于应用程序的设置方式。听起来最好的方法是用一个道具替换内部模态,该道具从一个高阶组件传递到模态,该组件还将打开/关闭功能传递给相关的子代:

// Modal.js
export default class ModalExampleControlled extends Component {
  render() {
    return (
      { this.props.open ?
      <Modal
        open={this.props.open}
        onClose={this.props.handleClose}
        size='small'
      >
        <Header icon='browser' content='Cookies policy' />
        <Modal.Content>
          <h3>This website uses cookies etc ...</h3>
        </Modal.Content>
        <Modal.Actions>
          <Button color='green' onClick={this.props.handleClose}>Got it</Button>
        </Modal.Actions>
      </Modal>
      : null }
    )
  }
}

// App.js
import { ProductList } from 'components';

class App extends Component  {
    handleOpen = () => this.setState({ open: true })
    handleClose = () => this.setState({ open: false })
    render(){
        return(
           <Segment>
             <Item.Group divided>
               <ProductList/>
             </Item.Group>
             <Modal open={this.state.open} closeModal={() => this.handleClose()}}
          </Segment>
        )
    }
}

export default App;

请记住,此代码只是示例性的,尚未完成。基本思想是:您需要将控制权交给需要访问它的所有其他组件之上的最高父组件。这样,您可以在需要时将打开/关闭功能传递给子代并控制模态。

如果大量通过,这可能会变得很笨拙。如果您的应用程序变得非常复杂,它将成为状态管理的问题。当发生大量事情时,像Redux这样的模式可能会帮助您从任何地方管理变化的状态(例如模式)。不过,根据您的情况,可能会找到它。