Dynamic content with React js Modal

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;

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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

Method 2

In the post onClick function set the post id/index in state along with the open flag

Inside the modal render use the saved index/id to pass that post to the modal as a param/prop.

You dont need to map over all posts inside the modal.

Sample

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

Method 3

Using React Hooks

Create a modal with dynamic props like this

export default function Modal({
  open,
  setOpen,
  onConfirm,
  title,
  description,
  confirmText,
})

Then render the component.
i did it like this
const getModal = () => {
    return (
        <Modal open={open} setOpen={setOpen} title={title} description={description} confirmText={confirmText} onConfirm={confirmAction} />
    )
}

and then when you want to display your dynamic modal
use a function like this
ConfirmAction can not be a function you should call the function inside that Modal according to that confirmation
const createModal = (title, description, confirmText, confirmAction) => {
    setTitle(title);
    setDescription(description);
    setConfirmText(confirmText);
    setConfirmAction(confirmAction);
    setOpen(true);
}

Method 4

Initialize your state with one array which will hold

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

Now modify render 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>
            );
        });
    }


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x