0

I'm trying to implement skeleton on my components, I'm using boolean to set if the components are loaded completely or not

Post.jsx (I guess here where the skeleton should show)

import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'
import 'react-loading-skeleton/dist/skeleton.css'
import styled from 'styled-components'

export default function Post({ post, isPostsLoading }) {
  moment.locale('ar');
  const daysAgo = moment(post.createdAt);

  const rowSkeletons = 6
  const GalleryStyles = styled.div`
    .gallery__grid {
        display: grid;
        gap: 2rem;
        grid-auto-flow: dense;
        grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
        justify-content: center;
    }
    .gallery__title {
        font-size: 2rem;
        padding: 1rem;
        text-align: center;
    }`
  if (isPostsLoading) {
    let rows = []
    for (let index = 0; index < rowSkeletons; index++) {
        rows.push(
            <section>
                <article className='item'>
                    <div className='item-img'>
                        <Skeleton width={140} height={140} />
                    </div>
                    <h3 className='item-title'><Skeleton count={4} /></h3>
                    <div className='item-info'>
                        <Skeleton width={160} height={20} />
                        <Skeleton width={30} height={20} />
                        <Skeleton width={22} height={22} circle={true} />
                    </div>
                    <Skeleton height={48} count={2} className='skeleton' />
                </article>
            </section>
        )
    }
    return (
        <SkeletonTheme color='#F5F5F5' highlightColor='#ffffff'>
            <GalleryStyles className='gallery__grid'>
                <h2 className='gallery__title'><Skeleton /></h2>
                <div className='gallery__grid'>
                    {rows}
                </div>
            </GalleryStyles>
        </SkeletonTheme>
    )
}
  return (
    <div className="post">
        <div>
        {post.photo && (
        <Link to={`/post/${post._id}`} className="link">
        <img
        className="postImg" 
        src={post.photo} 
        alt="" 
        />
        </Link>
        )}
        </div>
      <div className="postInfo">
        <Link to={`/post/${post._id}`} 
            className="link">
            <span className="postTitle">
              {post.title}
            </span>
        </Link>
        <div> 
            <p dir="auto" className="postDesc">
              {post.content}
            </p>
        </div>
            <span className="postDate">
              {daysAgo.fromNow()}
            </span>
        </div>
      </div>
    </div>
  );
}

I want each div shows a skeleton till i'ts fully loaded.

Posts.jsx (Here where an array of posts are showing)

import SearchIcon from '@mui/icons-material/Search';
import CircularProgress from '@mui/material/CircularProgress';

export default function Posts({ posts = [], isPostsLoading}) {
    const [filteredResults, setFilteredResults] = useState([]);
    const [searchInput, setSearchInput] = useState('');
    const [isLoading, setIsLoading] = useState(false);
// HERE isLoading is for search loading
    const filter = (e) => {
      const keyword = e.target.value;
        if (keyword !== '') {
            const filteredData = posts.filter((post) => {
                return Object.values(post)
                .join('')
                .toLowerCase()
                .includes(searchInput.toLowerCase())
            })
            setFilteredResults(filteredData)
        } else {
          setFilteredResults(posts)
        }
        setSearchInput(keyword);
    }
  return (
    <div className="posts">
      <div className="postsContainer">
      <div className="postsSearchContainer">
            <div className="postsSearch">
                  <div class="postsSearchIconContainer">
                      <SearchIcon class="w-5 h-5" />
                  </div>
                    <input type="text"
                    className="postsSearchInput"
                    placeholder=“search”
                    name="postsSearchText"
                    id="postsSearchText"
                    onChange={filter}
                    />
              </div>
              {/* ENDS OF POSTSSEARCHCONTAINER */}
      </div>
      {/* ENDS OF POSTSSEARCH */}
    <div className="postsBoxContainer">
      <div className="postsBox">
      {isLoading ? (
          <Box sx={{ display: 'flex' }}>
            <CircularProgress />
          </Box>
      ) : (
        filteredResults.length > 0 ? (
          filteredResults.map((filteredPosts) => (
            <Post post={filteredPosts} />
          ))
          ) : (posts.map((post) => (
            <Post isPostsLoading={isPostsLoading} post={post} />
          )) )
        )
        }
      </div>
      </div>
      {/* ENDS OF POSTSBOX */}
      </div>
      {/* ENDS OF POSTCONTAINER */}
    </div>
    //ENDS OF POSTS

  );
};

AllPosts.jsx (Here Where I'm using the api to fetch all the posts and using the boolean to know if it's loaded or not)

export default function AllPosts() {
  const [posts, setPosts] = useState([]);
  const { search } = useLocation();
  const [isPostsLoading, setIsPostsLoading] = useState(true);

  useEffect(() => {
    const fetchPosts = async () => {
      const res = await axios.get("/posts" + search);
      setPosts(res.data);
      setIsPostsLoading(false);
    };
    fetchPosts();
  }, [search]);

  return (
    <>
      <div className="posts">
        {/* <Header /> */}
        <div className="header">
        <div className="headerTitle">
            <span className="headerTitleLg">المقالات</span>
        </div>
        </div>
        <div className="postsContent">
        <Posts posts={posts} />
        </div>
      </div>
    </>
  );
}

The question is how to pass booleans as props to the other components

sultan.h
  • 331
  • 1
  • 4
  • 16

0 Answers0