Dynamic content with React js Modal

Basit picture Basit · Jan 23, 2019 · Viewed 10.7k times · Source

I want to get dynamic content with React js modal I am using package react-responsive-modal. First I render all the post through map. Now I want when I click the individual post the modal should pop up and show me only that particular post's title and body. Now I can't figure out how to get an individual post in modal. Is it possible to do that via third-party package or I have to make custom modal for that?

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;

Answer

ethan.roday picture ethan.roday · Jan 23, 2019

You'll need to introduce some additional state on your App component that keeps track of the currently selected post. In your onOpenModal() method, you can update that state with the index of the post that was clicked. Then, in renderModal(), you can check what the selected post is and only render that post instead of mapping over the entire array.

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