React 프로젝트: 인증이 있는 게시물의 해시태그 — 파트 #2

2부입니다. 이 블로그 게시물은 ReactJS 구성 요소를 분할하는 방법을 설명합니다.
ReactJ의 기초와 시작 방법에 대해 전혀 모르는 경우 link을 참조할 수 있습니다.

부품 시리즈에 대한 빠른 링크:

1 부 -
PART #2 - ReactJS는 UI를 구성 요소로 분할합니다. 구성 요소(이 게시물)
파트 #3 -
파트 #4 -
파트 #5 - styled-component의 고급 사용에 대한 기본 사항

어떤 단계에서든 막히면 Github repo을 참조하십시오.

완료된 프로젝트를 찾으려면 Demo link

Components let you split the UI into independent, reusable pieces, and think about each piece in isolation



React에서는 UI를 구성 요소별로 분할하는 것이 중요하므로 필요한 구성 요소 수를 확인하겠습니다.



보시다시피 7가지 구성 요소가 눈에 띕니다.
  • 헤더
  • 필터
  • 내비바
  • 저자
  • 게시물
  • 작성자 세부 정보
  • 온보딩 양식 | 디테일

  • 구성 요소를 만들 때 묻는 질문:

    내 구성 요소는 무엇을 해야 합니까?! 🤔

    상태 관리 — 구성 요소가 저장소를 구독합니다.
    데이터 가져오기 — 저장소에서 상태를 가져옵니다.
    UI 프리젠테이션 — 렌더링
    비즈니스 로직 — 애플리케이션의 비즈니스 로직과 연결되어 있습니다.

    구성 요소를 하나씩 설명하겠습니다.

    헤더 구성요소



    헤더 구성 요소는 매우 간단하며 프로젝트 제목을 포함합니다.

    import React from "react";
    
    const Heading = ({ title }) => {
      return (
        <div className="col">
          <h1>{title}</h1>
        </div>
      );
    };
    
    export default Heading;
    


    필터 구성요소



    필터 구성 요소는 다음과 같아야 합니다.
  • JSON 배열로 입력 필드 채우기
  • 필터 적용
  • 이 필터로 API 쿼리

  • 입력 상태를 저장하기 위해 이 구성 요소에서 사용자 지정 후크를 사용합니다.

    import React from 'react';
    import { useDispatch } from 'react-redux';
    
    import useFilterHook from '../../hooks/useFilterHooks';
    import { authorsFiltering } from './author-slice';
    import { useTranslation } from "react-i18next";
    
    
    const filterTypes = [
      {
        type: 'Radio',
        default: 'mr',
        selected: 'Mr',
        list: [
          { label: 'All', value: 'All' },
          { label: 'Mr.', value: 'mr' },
          { label: 'Miss.', value: 'miss' },
        ],
        optional: false,
        queryParamKey: 'title',
        placeholder: null,
        title: 'title',
      },
      {
        type: 'Text',
        default: '',
        selected: '',
        list: [],
        optional: false,
        queryParamKey: 'firstName',
        placeholder: 'Search by FirstName',
        title: 'first_name',
      },
      {
        type: 'Text',
        default: '',
        selected: '',
        list: [],
        optional: false,
        queryParamKey: 'lastName',
        placeholder: 'Search by LastName',
        title: 'last_name',
      },
      {
        type: 'Text',
        default: '',
        selected: '',
        list: [],
        optional: false,
        queryParamKey: 'email',
        placeholder: 'Search by Email',
        title: 'Email',
      },
    ];
    
    
    
    const Filter = () => {
      const dispatch = useDispatch();
      const { t: translation  } = useTranslation();
    
      const filtering = () => {
        dispatch(authorsFiltering({ search_keys: inputs }));
      }
    
      const {inputs, handleInputChange, handleSubmit} = useFilterHook({ }, filtering);
      return (
        <div>
          <h4> {translation('filters')} </h4>
          <form onSubmit={handleSubmit} autoComplete="off">
          {filterTypes.map((filter) => (
            <article className='card-group-item' key={`${filter.title}`}>
              <header className='card-header'>
                <h6 className='border-bottom border-3'>
                  {translation(filter.title)}
                </h6>
              </header>
                <div className='card-body'>
                  {filter.type === 'Radio' ? (
                    filter.list.map((item) => (
                      <label className='form-check' key={`${item.label}`}>
                        <input
                          type='radio'
                          name={filter.queryParamKey}
                          value={item.value} 
                          onChange={ handleInputChange}
    
                        />
                        <span className='form-check-label'> {item.label}</span>
                      </label>
                    ))
                  ) : (
                    <input
                      className='form-check-input'
                      type='text'
                      name={filter.queryParamKey}
                      onChange={handleInputChange}
                    />
                  )}
                </div>
            </article>
          ))}
          <br />
          <button type='submit' className='btn btn-primary left'>
            { translation('apply')}
          </button>
          </form>
        </div>
      );
    };
    
    Filter.displayName = 'Filter';
    export default Filter;
    
    


    작성자 구성 요소



    작성자 구성 요소는 다음을 수행해야 합니다.
  • 반응 쿼리를 사용하여 dummyAPi에서 작성자 가져오기
  • 이 배열 및 렌더링 목록에서 반복

  • import React, { useEffect, lazy } from 'react';
    import { useSelector, useDispatch } from 'react-redux';
    
    import { useAuthors } from './authors-hooks';
    import { authorSelector, authorsReceived } from './author-slice';
    
    const AuthorListView = lazy(() => import('./author-listing-view'));
    const NoResult = lazy(() => import('../../components/empty-list'));
    const Loader = lazy(() => import('../../components/loader'));
    
    const AuthorListing = () => {
    
      const { authors, filters: authorFilter } = useSelector(authorSelector);
      const dispatch = useDispatch();
    
      const { data, isFetching } = useAuthors();
      const renderStatus = data && data.data;
    
      useEffect(() => {
        if (renderStatus) {
          dispatch(authorsReceived(data.data));
        }
      }, [renderStatus]); // eslint-disable-line react-hooks/exhaustive-deps
    
      const authorItemList = authors.map((authorDetails) => {
        return (
          <AuthorListView
            key={`${authorDetails.firstName}-${authorDetails.lastName}`}
            user={authorDetails}
          />
        );
      });
    
      const authorFilterView = Object.keys(authorFilter).map((filter) => {
        return (
          <button class="btn btn-secondary ml-4">{filter.toUpperCase()} <span class="badge">{ authorFilter[filter] } </span></button>
        );
      });
    
      if (isFetching) {
        return <Loader />;
      }
      return <div>
        <div>{ authorFilterView }</div>
        {authors.length ? authorItemList : <NoResult />}
        </div>;
    };
    
    AuthorListing.displayName = 'AuthorsListing';
    export default AuthorListing;
    
    


    포스트 컴포넌트



    게시물 구성요소는 다음과 같아야 합니다.
  • 반응 쿼리를 사용하여 dummyAPi에서 게시물 가져오기
  • 이 배열 및 렌더링 목록에서 반복

  • import React, { lazy } from 'react';
    import { usePosts } from './posts-hooks';
    
    const PostListView = lazy(() => import('./post-listing-view'));
    const NoResult = lazy(() => import('../../components/empty-list'));
    const Loader = lazy(() => import('../../components/loader'));
    
    const PostsListing = () => {
      const { data, isFetching } = usePosts();
      const posts = (data && data.data) || [];
    
      const postItemList = posts.map((postDetails) => {
        return <PostListView key={`${postDetails.text}`} post={postDetails} />;
      });
    
      if (isFetching) {
        return <Loader />;
      }
      return <div>{posts.length ? postItemList : <NoResult />}</div>;
    };
    
    PostsListing.displayName = 'PostsListing';
    export default PostsListing;
    
    


    계속하려면

    좋은 웹페이지 즐겨찾기