根据 post id 显示模态

Show modal based on post id

我正在写我的博客并尝试实现 Sanity。我能够让我的 posts 与使用 useState 的查询返回的 json 对象一起显示 我正在尝试根据我用它的 _id 或某种键单击的 post 用正确的内容填充我的 React-Modal。我简化了代码,所以它不会太长:

export default function News() {
  // Json objects stored in posts 
  const [posts, setPosts] = useState([]);

  // Used to toggle Modal on and off
  const [isOpen, setIsOpen] = useState(false);
  function toggleModal() {
    setIsOpen(!isOpen);
  }

  return (
    <>
      {posts.map((posts) => (
        <div key={posts._id}>
           <h3 className="title" onClick={toggleModal}>
              {posts.title}
           </h3>
           <div">
              <a>
                <span onClick={toggleModal}>Read More</span>
              </a>
           </div>
           // Clicking on either span or a tag shows the Modal
            <Modal
               isOpen={isOpen}
               onRequestClose={toggleModal}>
               // Closes modal
              <button className="close-modal" onClick={toggleModal}>
                  <img
                    src="assets/img/svg/cancel.svg"
                    alt="close icon"/>
              </button>
              // Want to show content based on _id
              <h3 className="title">{posts.title}</h3>
              <p className="body">{posts.body}</p>
        </div>
      )
    </>
  )
}

每当我点击某个 post 时,它总是切换到第一个对象。 Click to see gif demo

Edit: I was able to get it to work based on the answer given

  const [state, setState] = useState({ isOpen: false, postId: null });

  const openModal = React.useCallback(
    (_key) => () => {
      setState({ isOpen: true, postId: _key });
    },
    []
  );

  function closeModal() {
    setState({ isOpen: false, postId: null });
  }

并且我添加了模态标签

key={post.id == state.postId}

现在每个 div 和标签都呈现正确的内容。 但是,我遇到了一个小问题。如果我单击 post[2],它会呈现出 post[0] 内容,眨眼间就会更改为正确的内容。然后,当我单击 post1 时,它会呈现 post[2] 内容并更改为正确的内容。它不断渲染之前的 post。这一切都在一瞬间,但仍然可见。

我可以建议使用 React Hooks 来解决你的问题。

您可以将一个函数传递给 useCallback 的 return,然后您可以通过将参数传递给它来在渲染中正常调用您的函数。

查看更多:https://reactjs.org/docs/hooks-reference.html#usecallback

import * as React from 'react';

export default function News() {
  // Json objects stored in posts 
  const [posts, setPosts] = useState([]);

  // Used to toggle Modal on and off
  const [isOpen, setIsOpen] = useState(false);
  
  // React.useCallback.
  const toggleModal = React.useCallback((id) => () => {
      setIsOpen(!isOpen);
      console.log(`Post id: ${id}`);
  }, []);

  return (
    <>
      {posts.map((post) => (
        <div key={post._id}>
           <h3 className="title" onClick={toggleModal(post._id)}>
              {post.title}
           </h3>
           <div">
              <a>
                <span onClick={toggleModal(post._id)}>Read More</span>
              </a>
           </div>
           // Clicking on either span or a tag shows the Modal
            <Modal
               isOpen={isOpen}
               onRequestClose={toggleModal(post._id)}>
               // Closes modal
              <button className="close-modal" onClick={toggleModal(post._id)}>
                  <img
                    src="assets/img/svg/cancel.svg"
                    alt="close icon"/>
              </button>
              // Want to show content based on _id
              <h3 className="title">{post.title}</h3>
              <p className="body">{post.body}</p>
        </div>
      )
    </>
  )
}