리액트 슬랙 클론코딩 #3

Hyeonu_J·2022년 1월 21일
0
post-custom-banner


배운 것 :

input 이 있는 컴포넌트는 따로 분리해주자!
(안그러면 다른 부분이 리렌더링 되서 최적화 할 때 불편하다)


Workspace/index.tsx

                <Channels>
                    <WorkspaceName onClick={toggleWorkspaceModal}>
                    Sleact
                    </WorkspaceName>
                    <MenuScroll>
                        <Menu show={showWorkspaceModal} onCloseModal={toggleWorkspaceModal} style={{top:95,left:80}}>
                            <WorkspaceModal>
                                <h2>Sleact</h2>
                                <button onClick={onClickAddChannel}>채널 만들기</button>
                                <button onClick={onLogout}>로그아웃</button>
                            </WorkspaceModal>
                        </Menu>
                    </MenuScroll>
                </Channels>

CreateChannelModal/index.tsx

    return (
        <Modal show={show} onCloseModal={onCloseModal}>
            <form onSubmit={onCreateChannel}>
                <Label id="channel-label">
                    <span>채널</span>
                    <Input id="channel" value={newChannel} onChange={onChangeNewChannel}/>
                </Label>
                <Button type="submit">생성하기</Button>
            </form>
        </Modal>
    )

코드 스플리팅에 대한것

App.tsx

const App = () => {
  return (
    <Switch> 
      <Redirect exact path="/" to="/login"/>
      <Route path="/login" component={LogIn}/>
      <Route path="/signup" component={SignUp}/>
      {/* '/workspace/channel', 'workspace/dm' 이 아니라
      아래처럼 주소칸 뒤에 클론을 붙이면 특수한 역할(와일드카드) 역할을 한다.*/}
      <Route path="/workspace/:workspace" component={Workspace}/>
      {/* 또한 예를 들어 여기에 workspace/channel 주소가 있으면 실행이 안 된다 */}
    </Switch>
  )
};

Workspace/index.tsx

...(생략)...
                    <Switch>
                        <Route path="/workspace/:workspace/channel/:channel" component={Channel}/>
                        <Route path="/workspace/:workspace/dm/:id" component={DirectMessage}/>
                    </Switch>
...(생략)...

CreateChannelModal/index.tsx

// useParams 훅으로 위에 써져있는 파라미터 뒤의 값들을 불러올 수 있다!
import { useParams } from 'react-router';
...(생략)...

    const { workspace, channel } = useParams<{workspace:string;channel:string}>();
    const onCreateChannel=useCallback(()=>{
        axios.post(`/api/workspaces/${workspace}/channels`,{
            name:newChannel,    
        },{
            withCredentials:true //쿠키전달
        })
    },[newChannel]);

위에 gif처럼 채널을 만드는 모달에 적용된 코드이다.
보고 이해하지

import Modal from '@components/Modal'
import useInput from '@hooks/useInput';
import { Button, Input, Label } from '@pages/SignUp/styles';
import { IChannel, IUser } from '@typings/db';
import fetcher from '@utils/fetcher';
import axios from 'axios';
import React, { useCallback, VFC } from 'react';
import { useParams } from 'react-router';
import { toast } from 'react-toastify';
import useSWR from 'swr';

interface Props{
    show:boolean;
    onCloseModal:()=>void;
    setShowCreateChannelModal:(flag:boolean) => void;
}
const CreateChannelModal:VFC<Props> = ({show,onCloseModal,setShowCreateChannelModal}) => {
    const [newChannel,onChangeNewChannel,setNewChannel] = useInput('');
    const { workspace, channel } = useParams<{workspace:string;channel:string}>();
    const { data:userData, error,mutate} = useSWR<IUser|false>(
        'http://localhost:3095/api/users',
        fetcher,
        {
            dedupingInterval:2000,
        }
    );
    const {data:channelData,mutate:mutateChannel} = useSWR<IChannel[]>(
        userData ? `http://localhost:3095/api/workspaces/${workspace}/channels` : null,
        fetcher,
    )

    const onCreateChannel=useCallback((e)=>{
        e.preventDefault();
        axios.post(`http://localhost:3095/api/workspaces/${workspace}/channels`,{
            name:newChannel,    
        },{
            withCredentials:true //쿠키전달
        },)
        .then(() => {
            setShowCreateChannelModal(false);
            mutateChannel()
            setNewChannel('')
        })
        .catch((error)=>{
            console.dir(error);
            toast.error(error.response?.data, {position:'bottom-center'});
        })
    },[newChannel]);
    
    return (
        <Modal show={show} onCloseModal={onCloseModal}>
            <form onSubmit={onCreateChannel}>
                <Label id="channel-label">
                    <span>채널</span>
                    <Input id="channel" value={newChannel} onChange={onChangeNewChannel}/>
                </Label>
                <Button type="submit">생성하기</Button>
            </form>
        </Modal>
    )
}

export default CreateChannelModal
profile
흔한 컴공러 / 3학년
post-custom-banner

0개의 댓글