使用 React js Modal 的动态内容

IT技术 javascript reactjs react-modal
2021-05-09 02:01:58

我想使用 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;
3个回答

您需要在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>
    );
  }
}

在 post onClick 函数中,将 post id/index 设置为 state 以及 open flag

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

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

样本

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

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

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