SENTENCE U | Day 10 (온라인 유저/레이아웃/글작성 모달창)

블로그 이사 완료·2023년 1월 26일
0
post-thumbnail

전체 유저에서 접속중인 유저만 불들어오도록 변경

서버에서 전체 유저 리스트를 받아와 현재 온라인인 유저만 불이 들어오도록 했다.

일단 useQuery를 사용한 서버의 전체 유저 데이터를 받아왔다.

  const { allUsers } = useAllUsers();

그리고 실시간으로 접속중인 유저의 데이터는 socket.io를 사용해서 가져오고 allUsers,onlineList는 모두 이름 순으로 정렬시켰다.

  useEffect(() => {
    // 서버에서 온라인 리스트 배열로 받음
    socket?.on('onlineList', (data) => {
      // 배열에서 중복요소 제거해서 새로운 배열 생성
      const userArray = data.filter((ele, i) => {
        return data.indexOf(ele) === i;
      });
      // 새로운 배열 온라인리스트 state에 저장
      setOnlineList(userArray);
    });
    return () => {
      socket?.off('onlineList');
    };
  }, [socket, onlineList]);

  if (allUsers && onlineList) {
    allUsers.sort();
    onlineList.sort();
  }

전체 유저의 리스트를 map함수로 반복시킬 때 온라인 유저는 클래스 isOnline true만들어 CSS로 처리했다.

<Container>
        접속중인 유저
        {allUsers.map((user, i) => {
          const isOnline = onlineList.indexOf(user);
          return (
            <List className={isOnline < 0 ? 'offline' : 'online'} key={i}>
              {user}
            </List>
          );
        })}
      </Container>
export const List = styled.div`
  position: relative;
  text-indent: 20px;
  margin: 15px;
  &:before {
    content: '';
    display: block;
    position: absolute;
    top: 50%;
    left: 0;
    transform: translate(0, -50%);
    width: 10px;
    height: 10px;
    border-radius: 50%;
    border: 1px solid var(--gray);
  }
  &.online:before {
    background-color: var(--blue);
    border: none;
  }
`;


NavBar/홈페이지 UI스타일적용

NavBar는 필요한 메뉴, 로고, 프로필의 정보만 구성했고, 홈페이지에는 랜덤으로 바뀌는 포스터 구역과, 베스트/최신글, 온라인 유저로 구성해놨다.10px


글쓰기 모달창으로 변경

기존에는 홈페이지에서 바로 글을 작성 할 수 있도록 설정해놨는데 디자인 적으로 너무 뜬금 없이 배치되었다고 판단했다.

글쓰기 WRITE 메뉴나, 플로팅 버튼을 누르면 모달창이 나올수 있도록 구현했다.

모달창을 적용하면서 모달창 밖의 영역을 클릭 시 모달창이 닫힐 수 있도록 useOnClickOutsideModal 커스텀 Hook함수를 생성했다.

import React, { useEffect } from 'react';

function useOnClickOutsideModal(ref, handler) {
  useEffect(() => {
    // console.log(ref);

    const listener = (e) => {
      if (!ref.current || ref.current.contains(e.target)) {
        return;
      }
      handler(e);
    };
    document.addEventListener('mousedown', listener);
    document.addEventListener('touchstart', listener);

    return () => {
      // 컴포넌트가 언마운트 됐을 때 리턴 실행 (이벤트리스너들 삭제)
      document.removeEventListener('mousedown', listener);
      document.removeEventListener('touchstart', listener);
    };
  }, [ref, handler]);

  return <div>useOnClickOutside</div>;
}

export default useOnClickOutsideModal;

모달창의 Form 태그를 useRef를 사용해서 DOM element를 선택할 수 있도록했다.

그리고 위의 Hook 함수는 클릭한 영역이 해당하는 ref와 동일하지 않을 경우 모달창을 닫는 stat를 false로 만들어준다.

 useOnClickOutsideModal(ref, () => {
    setWirteModalOpen(false);
    setIsBtnActive(false);
  });

  return (
    <Container>
      <Form onSubmit={onSubmit} ref={ref}>
        <FormHeader>LIFE IS A SENTENCE</FormHeader>
        <Input
          autoFocus
          autoComplete='off'
          type='text'
          name='post-writeModal'
          id='post-write-label'
          placeholder='들려주고 싶은 한 마디를 적어보세요. (최대 20자, 한글만 가능)'
          value={sentence}
          onChange={onChangeSentence}
        />
        <Button buttonActive={buttonActive} id='Button' type='submit'>
          작성 완료
        </Button>
      </Form>
    </Container>
  );

모달창의 바깥 영역을 클릭하면 닫히는 것을 확인 할 수 있다.

profile
https://kyledev.tistory.com/

0개의 댓글