1. 로그인 여부에 따라 각기 다른 페이지를 연결하는 방법

    import React from 'react';
    import { Redirect, Route } from 'react-router-dom';
    import { useUserState } from '../contexts/UserContext';
    
    function PrivateRoute({ component: Component, ...rest }) {
    	const { userName } = useUserState();
    	return <Route {...rest} render={(props) => (userName ? <Redirect to="/category" /> : <Component {...props} />)} />;
    }
    
    export default PrivateRoute;
    
    function App() {
    	return (
    			<Header />
    			<PrivateRoute path="/" exact component={Home} />
    			<Route path="/login" component={Login} />
    			<Route path="/join" component={Join} />
    			<Route path="/category" component={Category} />
    		</AppProvider>
    	);
    }
    
  2. 코드의 가독성을 지키며 Context API를 여러개 사용하는 방법

    const AppProvider = ({ contexts, children }) =>
    	contexts.reduce(
    		(prev, context) =>
    			React.createElement(context, {
    				children: prev,
    			}),
    		children
    	);
    
    function App() {
    	return (
    		<AppProvider contexts={[UserProvider, HeaderProvider]}>
    			<Header />
    			<PrivateRoute path="/" exact component={Home} />
    			<Route path="/login" component={Login} />
    			<Route path="/join" component={Join} />
    			<Route path="/category" component={Category} />
    		</AppProvider>
    	);
    }
    
  3. 조건부 라우팅하는 방법

    1. input 입력 끝난후에 특정 함수 실행시키는 방법
    <input name="id" value={id} onChange={onChange} onBlur={함수명}/>
    
    1. chrome에서 text-align 적용하는 방법
    .auth {
    	position: relative;
    	text-align: center;
    	**margin: 0;**
    }
    
    1. div 가운데 정렬하는 방법
    .auth-form {
    	position: relative;
    	width: 50%;
    	**margin: 0 auto;**
    	text-align: center;
    	background-color: pink;
    }
    
    1. 버튼 안에 이미지와 텍스트를 함께 배치하는 방법
    .social-image {
    	**float: left;**
    	width: 38px;
    	height: 38px;
    	padding-left: 3%;
    }
    

    1. div영역에서 버튼을 오른쪽에 정렬하는 방법

    ⇒ div의 children 엘리먼트가 두개이고 버튼의 div영역이 두번째 엘리먼트일 경우에 해당되는 방법

    .header {
    	display: flex;
    	**justify-content: space-between;**
    	width: 100%;
    	height: 90px;
    	bottom: 90%;
    }
    
    1. 카테고리 클릭 시 스타일 변경하는 방법
    1. input 박스 클릭시 테두리 안생기게 하는법
    .search-input {
    	width: 77%;
    	margin-left: 3%;
    	border: 0px;
    	**&:focus {
    		outline: none;
    	}**
    }
    
    1. checkbox 디자인 변경하는 방법
    1. input태그와 span태그를 감싸는 label태그 생성
    2. input type을 checkbox로 지정
    3. span태그를 input태그 밑에 작성
    <label className="check-label">
    									<input
    										className="check-input"
    										id={post.id}
    										type="checkbox"
    										key={getKey(post.id, 'input')}
    										onClick={(e) => {
    											console.log(e.target.id);
    										}}
    									/>
    									<span className="check-box"></span>
    								</label>
    
    1. label에선 원하는대로 속성값을 설정함
    2. input은 display: none으로 설정
    3. span에서는 체크박스가 선택되지 않았을 경우의 속성을 설정
    4. input:checked ~ .span에서는 체크박스가 선택됐을 경우의 배경을 설정
    .check-label {
    	display: flex;
    	align-items: center;
    	margin-right: 1%;
    }
    
    .check-input {
    	display: none;
    }
    
    .check-box {
    	display: inline-block;
    	width: 15.5px;
    	height: 15.5px;
    	border: 1px solid $blue;
    	box-sizing: border-box;
    	cursor: pointer;
    	background-color: $white;
    	border-radius: 2px;
    }
    
    .check-input:checked ~ .check-box {
    	background: url(../common/icon/checkIcon.png) $blue no-repeat center/10px;
    }
    
    1. checkbox 상태관리하는방법
    1. 특정 아이템 선택하는 방법

      1. 체크박스값이 바뀔때마다 해당 체크박스의 checked여부에 따라 아이템을 checkedItems에 추가하거나 삭제한다.

      2. checked속성은 해당 아이템이 checkedItems에 포함되어 있다면 true, 포함되어 있지않다면 false이다.

        ⇒ 처음에는 각 Post 컴포넌트에서 생성한 state변수를 사용함. 하지만 이렇게 하면 각 컴포넌트의 체크박스의 state 변수들을 한번에 초기화할 수 없어서 방법 변경함

      // Post.js
      const { checkedItems } = useCheckedItemsState();
      const checkedItemsDispatch = useCheckedItemsDispatch();
      const { checkBoxVisibility } = useCheckBoxVisibilityState();
      
      const checkHandler = ({ target }) => {
      	if (target.checked) {
      		checkedItemsDispatch({ type: 'ADD_ITEM', item: post.id });
      	} else {
      		checkedItemsDispatch({ type: 'DELETE_ITEM', item: post.id });
      	}
      ;
      
      ...
      {checkBoxVisibility && (
      				<label className="check-label">
      					<input
      						className="check-input"
      						type="checkbox"
      						onChange={(e) => {
      							checkHandler(e);
      						}}
      						checked={checkedItems.includes(post.id)}
      					/>
      					<span className="check-box"></span>
      				</label>
      ...
      
      
    2. 전체 아이템 선택하는 방법

      1. 전체선택 체크박스값이 바뀔때마다 checked여부에 따라 각기 다르게 진행한다.

        1. checked가 true일 경우

        ⇒ isAllChecked를 true로 변경하고 현재 렌더링 된 아이템들 중 checkedItems에 포함되지 않은 아이템들만 새로 checkedItems에 추가한다.

        1. checked가 false일 경우

        ⇒ isAllChecked를 false로 변경하고 checkedItems를 초기화한다.

      2. CheckBoxVisibility가 false로 변경되거나 아이템 삭제가 완료된 후에는 isAllChecked를 false로 변경하며 checkedItems를 초기화한다.

      // PostList.js
      const { checkedItems } = useCheckedItemsState();
      const { isAllChecked } = useIsAllCheckedState();
      const isAllCheckedDispatch = useIsAllCheckedDispatch();
      const checkedItemsDispatch = useCheckedItemsDispatch();
      const { checkBoxVisibility } = useCheckBoxVisibilityState();
      const checkBoxVisibilityDispatch = useCheckBoxVisibilityDispatch();
      
      const resetCheckedItems = () => {
      		isAllCheckedDispatch({ type: 'NOT_CHECKED' });
      		checkedItemsDispatch({ type: 'RESET_ITEM' });
      	};
      
      	const allCheckedHandler = ({ target }) => {
      		if (target.checked) {
      			isAllCheckedDispatch({ type: 'CHECKED' });
      			postList.map((post) => {
      				if (!checkedItems.includes(post.id)) {
      					checkedItemsDispatch({ type: 'ADD_ITEM', item: post.id });
      				}
      			});
      		} else {
      			resetCheckedItems();
      		}
      	};
      
      ...
      {checkBoxVisibility && (
      		<>
      			<label className="check-label">
      				<input
      					className="check-input"
      					type="checkbox"
      					checked={isAllChecked}
      					onChange={(e) => {
      						allCheckedHandler(e);
      					}}
      				/>
      				<span className="check-box"></span>
      			</label>
      			<span className={classNames('text', 'post-list', 'bold')}>{Words.ALL_CHECK}</span>
      		</>
      )}
      ...
      
    3. 카테고리가 변경되거나 아이템 삭제가 완료된 후, 또한 삭제버튼이 새로 클릭될때마다 isAllChecked를 false로 변경하고 checkedItems를 초기화해야한다.

  4. 객체형태의 배열의 특정 원소들만 문자열로 변환하는 방법

  5. CORS(Cross Origin Resource Sharing)

  1. SOP(Same-Origin Policy)

  2. pagination 구현하는 방법

  1. div의 width를 auto로 지정하면서 가운데에 놓는 방법

  2. axios 이용해서 form-data 전송하기

  3. 변수와 헤더 정보 동시에 API로 보내기

  4. postList.js는 총 4번 렌더링 됨

  5. keywords 중복 검사 및 갯수 제한하는 방법

  6. option에서 value 두개 받는 방법

  7. inline-block으로 설정된 div내에서 top, bottom 등 설정하는 방법