【问题标题】:Dynamic content with React js Modal使用 React js Modal 的动态内容
【发布时间】:2019-06-16 11:46:00
【问题描述】:

我想使用 React js modal 获取动态内容,我正在使用包 react-responsive-modal。首先,我通过地图渲染所有帖子。现在我希望当我单击单个帖子时,模式应该弹出并只显示该特定帖子的标题和正文。现在我不知道如何在模态中获取单个帖子。 是否可以通过第三方包做到这一点,或者我必须为此制作自定义模式?

import React from 'react';
    import Modal from 'react-responsive-modal';
    import Axios from 'axios';

    const styles = {
        fontFamily: 'sans-serif',
        textAlign: 'center'
    };

    class App extends React.Component {
        state = {
            posts: [],
            open: false
        };

        componentDidMount() {
            let url = 'https://jsonplaceholder.typicode.com/posts';
            Axios.get(url).then(res => {
                this.setState({
                    posts: res.data.slice(0, 10)
                });
                console.log(res.data.slice(0, 10));
            });
        }

        onOpenModal = () => {
            this.setState({ open: true });
        };

        onCloseModal = () => {
            this.setState({ open: false });
        };

        renderPosts() {
            return this.state.posts.map(post => {
                return (
                    <div
                        key={post.id}
                        style={{ width: 400, height: 400, backgroundColor: 'orange' }}
                        onClick={this.onOpenModal}
                    >
                        <h1>{post.title}</h1>
                    </div>
                );
            });
        }

        renderModal(id, title, body) {
            return this.state.posts.map(post => {
                return (
                    <div key={post.id} style={{ width: 400, height: 400, backgroundColor: 'orange' }}>
                        <h1>{post.id}</h1>
                        <h1>{post.title}</h1>
                        <p>{post.body}</p>
                    </div>
                );
            });
        }

        render() {
            const { open } = this.state;
            return (
                <div style={styles}>
                    <h2>react-responsive-modal</h2>

                    <div>{this.renderPosts()}</div>
                    <Modal open={open} onClose={this.onCloseModal} center>
                        <h2>Simple centered modal</h2>
                        <div>{this.renderModal()}</div>
                    </Modal>
                </div>
            );
        }
    }

    export default App;

【问题讨论】:

    标签: javascript reactjs react-modal


    【解决方案1】:

    您需要在 App 组件上引入一些额外的状态,以跟踪当前选定的帖子。在您的 onOpenModal() 方法中,您可以使用被点击的帖子的索引来更新该状态。然后,在renderModal() 中,您可以检查所选帖子是什么,并且只渲染该帖子而不是映射到整个数组。

    class App extends React.Component {
      state = {
        posts: [],
        open: false,
        selectedPost: null // Keep track of the selected post
      };
    
      componentDidMount() {
        let url = "https://jsonplaceholder.typicode.com/posts";
        Axios.get(url).then(res => {
          this.setState({
            posts: res.data.slice(0, 10)
          });
          console.log(res.data.slice(0, 10));
        });
      }
    
      onOpenModal = i => {
        this.setState({
          open: true,
          selectedPost: i // When a post is clicked, mark it as selected
        });
      };
    
      onCloseModal = () => {
        this.setState({ open: false });
      };
    
      renderPosts = () => {
        return this.state.posts.map((post, i) => {
          return (
            <div
              key={post.id}
              style={{ width: 400, height: 400, backgroundColor: "orange" }}
              onClick={() => this.onOpenModal(i)} // Pass the id of the clicked post
            >
              <h1>{post.title}</h1>
            </div>
          );
        });
      }
    
      renderModal = () => {
        // Check to see if there's a selected post. If so, render it.
        if (this.state.selectedPost !== null) {
          const post = this.state.posts[this.state.selectedPost];
          return (
            <div
              style={{ width: 400, height: 400, backgroundColor: "orange" }}
            >
              <h1>{post.id}</h1>
              <h1>{post.title}</h1>
              <p>{post.body}</p>
            </div>
          );
        }
      }
    
      render() {
        const { open } = this.state;
        return (
          <div style={styles}>
            <h2>react-responsive-modal</h2>
    
            <div>{this.renderPosts()}</div>
            <Modal open={open} onClose={this.onCloseModal} center>
              <h2>Simple centered modal</h2>
              <div>{this.renderModal()}</div>
            </Modal>
          </div>
        );
      }
    }
    

    【讨论】:

    • 为什么要在要渲染的 div 上放置 key 属性?如果你不这样做会有什么不同?
    • 那是不必要的 - 我只是使用你现有的代码而忽略了删除它。
    • 更新了答案!
    • 实际上,我(不是 OP,顺便说一句)会认为它是必要的,至少在某些情况下是这样。即使您没有迭代元素,提供 key prop 也很有用,因为它会导致重新安装整个元素,而不仅仅是部分更新。这有时是可取的,这种模式可能是其中一种情况。如果您不使用 key prop,react 将尝试重用尽可能多的 DOM 元素的相同实例。有时你想要,有时你不想要。
    • @GarrettMotzner 这当然是对的,当你想通过强制重新挂载来重置特定组件的状态时,key props 可能很有用,但一般来说 React 应该能够有效地处理在这种情况下进行差异和渲染,无需任何人工干预。
    【解决方案2】:

    用一个数组初始化你的状态

    state = {
            posts: [],
            open: false,
            modalShow: [false,false,false,false,false,false,false,false,false,false] // this is 10 as you have only 10 posts
        };
    

    现在修改渲染帖子

        onOpenModal = (id) => {
            const newModalShow = [...this.state.modalShow];
            newModalShow[id] = true; 
            this.setState({ modalShow: newModalShow});
        };
    
    
        renderPosts() {
            return this.state.posts.map((post,index) => {
                return (
                    <Fragement>
                    <div
                        key={post.id}
                        style={{ width: 400, height: 400, backgroundColor: 'orange' }}
                        onClick={()=>this.onOpenModal(index)}
                    >
                        <h1>{post.title}</h1>
                    </div>
                    <Modal open={this.state.modalShow[index]} onClose={this.onCloseModal} center>
                        <h2>post.title</h2>
                        <div>{this.renderModal()}</div>
                    </Modal>
                   <Fragement>
                );
            });
        }
    

    【讨论】:

    • 为什么要渲染所有可能的模态但隐藏它们,而不是仅仅渲染活动的模态,并在状态改变时改变它?此外,是否有更好的方法来跟踪每个帖子的可见状态,而不是静态长度数组?
    【解决方案3】:

    在 post onClick 函数中,将 post id/index 与打开标志一起设置为 state

    在模态渲染中,使用保存的索引/ID 将该帖子作为参数/道具传递给模态。

    您不需要映射模式内的所有帖子。

    样本

    onOpenModal = (index) => {
       this.setState({ open: true, selectedPostIndex: index });
    };
    
    onCloseModal = () => {
       this.setState({ open: false, selectedPostIndex: undefined })
    }
    
    renderPosts() {
       return this.state.posts.map((post, index) => {
          return (
             <div key={post.id} onClick={() => this.onOpenModal(index)}>
                <h1>{post.title}</h1>
             </div>
          )
       })
    }
    
    render() {
    ....
      <Modal open={open} onClose={this.onCloseModal} center>
        <h2>Simple centered modal</h2>
        <div>{this.renderModal(this.state.posts[this.state.selectedPostIndex])}</div>
      </Modal>
     ....
    }
    
    renderModal(post) {
       return (
          <div key={post.id} style={{ width: 400, height: 400, backgroundColor: 'orange' }}>
             <h1>{post.id}</h1>
             <h1>{post.title}</h1>
             <p>{post.body}</p>
          </div>
       )
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-16
      • 2018-04-24
      • 1970-01-01
      • 2019-06-03
      • 1970-01-01
      • 2017-08-26
      • 2019-03-25
      • 2021-07-05
      相关资源
      最近更新 更多