본문 바로가기
나도 공부한다/삽질

(React) API로 받아온 값을 상태값에 넣어주기 전에 화면이 렌더링되는 문제

by 꾸빵이 2024. 1. 18.

여기서 followData, flowerData가 쓰이지 않아 setFollowData, setFollowerData는 불필요한 코드라고 생각했고 지웠다. 그랬더니 새로고침 했을 때 잘만 나오던 팔로우 목록이 화면에서 보이지 않았다. 버튼을 눌러야만 보였다. 상태를 업데이트하면 컴포넌트가 리렌더링 되는데 set함수를 지워버리니 리렌더링할 요소가 없어 컴포넌트가 이전 상태를 유지하는게 원인이었다.

import React, { useEffect } from 'react';
import { useState } from 'react';
import axios from 'axios';

const menuArr = [
    { name: '팔로우', content: [] },
    { name: '팔로워', content: [] },
];

function FollowList() {
    const [currentTab, setCurrentTab] = useState(0);
    const [followData, setFollowData] = useState([]);
    const [followerData, setFollowerData] = useState([]);

    useEffect(() => {
        const fetchData = async () => {
            try {
                const [followResponse, followerResponse] = await axios.all([
                    axios.get(
                    ),
                    axios.get(
                    ),
                ]);

                setFollowData(followResponse.data);
                setFollowerData(followerResponse.data);

                // 데이터를 받은 후에 content를 설정
                menuArr[0].content = followResponse.data.map(
                    (it) => it.userName
                );
                menuArr[1].content = followerResponse.data.map(
                    (it) => it.userName
                );
            } catch (error) {
                console.error(error);
            }
        };

        fetchData();
    }, []);

    return (
        <div className="FollowList">
            {menuArr.map((data, index) => {
                return (
                    <div>
                        <button
                            key={index}
                            onClick={() => setCurrentTab(index)}
                            className={
                                currentTab === index
                                    ? 'currentFocused'
                                    : 'Focused'
                            }
                        >
                            {data.name}
                        </button>
                    </div>
                );
            })}
            <p>{menuArr[currentTab].content}</p>
        </div>
    );
}

export default FollowList;

 

 

처음엔 이렇게 억지로 리렌더링되게 만들었다. 그런데 좀 찝찝... 그리고 menuArr 인덱스에 하드코딩으로 접근해서 데이터를 넣는거라 코드를 개선하고 싶었다.

import React, { useEffect } from 'react';
import { useState } from 'react';
import axios from 'axios';

const menuArr = [
    { name: '팔로우', content: [] },
    { name: '팔로워', content: [] },
];

function FollowList() {
    const [currentTab, setCurrentTab] = useState(1);

    useEffect(() => {
        const fetchData = async () => {
            try {
                const [followResponse, followerResponse] = await axios.all([
                    axios.get(
                    ),
                    axios.get(
                    ),
                ]);

                // 데이터를 받은 후에 content를 설정
                menuArr[0].content = followResponse.data.map(
                    (it) => it.userName
                );
                menuArr[1].content = followerResponse.data.map(
                    (it) => it.userName
                );

                setCurrentTab(0);
            } catch (error) {
                console.error(error);
            }
        };

        fetchData();
    }, []);

    return (
        <div className="FollowList">
            {menuArr.map((data, index) => {
                return (
                    <div>
                        <button
                            key={index}
                            onClick={() => setCurrentTab(index)}
                            className={
                                currentTab === index
                                    ? 'currentFocused'
                                    : 'Focused'
                            }
                        >
                            {data.name}
                        </button>
                    </div>
                );
            })}
            <p>{menuArr[currentTab].content}</p>
        </div>
    );
}

export default FollowList;

 

 

생각해보니까 팔로우, 팔로워 목록은 자주 변경되는 데이터가 아니다. 그래서 마운트 될 때마다 똑같은 데이터를 content에 계속 넣어주는 동작은 불필요하다고 생각했다. useMemo를 이용해서 만약 팔로우, 팔로워 목록이 이전과 같으면 변경을 하지 않도록 수정했다. 이렇게 만들면 useEffect 내부에서 상태를 변경해야하고, 리렌더링을 해서 업데이트된 상태값을 화면에 바로 보여줄 수 있었다.

import React, { useEffect, useMemo, useState } from 'react';
import axios from 'axios';

function FollowList() {
    const [currentTab, setCurrentTab] = useState(0);
    const [followData, setFollowData] = useState([]);
    const [followerData, setFollowerData] = useState([]);

    const menuArr = useMemo(() => {
        // 데이터를 받은 후에 content를 설정
        const followContent = followData.map((it) => it.userName);
        const followerContent = followerData.map((it) => it.userName);

        return [
            { name: '팔로우', content: followContent },
            { name: '팔로워', content: followerContent },
        ];
    }, [followData, followerData]);

    useEffect(() => {
        const fetchData = async () => {
            try {
                const [followResponse, followerResponse] = await axios.all([
                    axios.get(
                    ),
                    axios.get(
                    ),
                ]);

                setFollowData(followResponse.data);
                setFollowerData(followerResponse.data);
            } catch (error) {
                console.error(error);
            }
        };

        fetchData();
    }, []);

    return (
        <div className="FollowList">
            {menuArr.map((data, index) => (
                <div key={index}>
                    <button
                        onClick={() => setCurrentTab(index)}
                        className={
                            currentTab === index ? 'currentFocusedTab' : 'Tab'
                        }
                    >
                        {data.name}
                    </button>
                </div>
            ))}
            <ul>
                {menuArr[currentTab].content.map((userName, index) => (
                    <li key={index}>
                        <p>{userName}</p>
                        <button>언팔로우</button>
                    </li>
                ))}
            </ul>
        </div>
    );
}

export default FollowList;