somn45 / mucketlist

React, Typescript, Spotify API를 이용해 좋아하는 장르의 곡을 지속적으로 추적, 몰랐던 명곡을 저장할 수 있는 APP
0 stars 0 forks source link

Redux-toolkit 사용 중 경고 메세지 발생 #1

Closed somn45 closed 2 years ago

somn45 commented 2 years ago

redux toolkit으로 Home 컴포넌트에 상태를 뿌려줄 때 다음과 같은 경고 메시지가 발생함

 Cannot update a component (`Connect(Home)`) while rendering a different component (`Connect(Genre)`). To locate the bad setState() 
 call inside `Connect(Genre)`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render

메세지의 내용으로는 setState를 잘못된 위치에 배정한 것이 원인이라고 나오는데 이에 대해 정확한 원인을 찾아 해결해야 한다. Home 컴포넌트와 Genre 컴포넌트의 코드는 아래와 같다.

// Home
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Cookies } from 'react-cookie';
import axios from 'axios';
import { connect } from 'react-redux';
import Genre from '../components/Genre';

interface HomeProps {
  selectedGenre: string[];
}

const cookies = new Cookies();

function Home({ selectedGenre }: HomeProps) {
  const navigate = useNavigate();
  const [genres, setGenres] = useState<string[]>([]);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    getSpotifyGenres();
    if (!cookies.get('F_UID')) navigate('/login');
  }, []);
  const getSpotifyGenres = async () => {
    const accessToken = cookies.get('accessToken');
    const response = await axios.post(`http://localhost:3001/genres`, {
      accessToken: accessToken,
    });
    setGenres(response.data.genres);
    setLoading(false);
  };

  const onClick = async (e: React.MouseEvent<HTMLInputElement>) => {
    e.preventDefault();
    /*
    const accessToken = cookies.get('accessToken');
    console.log(accessToken);
    const response = await axios.get(
      `http://localhost:3001/search?accessToken=${accessToken}`
    );
    */
  };
  return (
    <div>
      <h2>Home</h2>
      <form>
        {loading ? (
          <h2>장르 목록을 불러오는 중입니다.</h2>
        ) : (
          <>
            {genres.map((genre) => (
              <Genre key={genre} genre={genre} />
            ))}
          </>
        )}
        <input
          type="submit"
          value="Search your favorite genres"
          onClick={onClick}
        />
      </form>
    </div>
  );
}

function mapStateToProps(state: string[]) {
  return { selectedGenre: state };
}

export default connect(mapStateToProps)(Home);
// Genre
import React, { useState } from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { addGenre, removeGenre } from '../store/store';

interface GenreProps {
  genre: string;
}

interface GenreState {
  selectedGenre: string;
}

function Genre({ genre }: GenreProps) {
  const [checked, setChecked] = useState(false);
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setChecked((prevState) => !prevState);
    const currentElement = e.target;
  };
  return (
    <>
      <input
        type="checkbox"
        name={genre}
        checked={checked}
        onChange={handleChange}
      />
      {genre}
    </>
  );
}

function mapDispatchToProps(dispatch: Dispatch, ownProps: GenreProps) {
  return {
    addGenre: dispatch(addGenre(ownProps)),
  };
}

export default connect(null, mapDispatchToProps)(Genre);
somn45 commented 2 years ago

문제 해결함

원인은 Genre에서 호출된 mapDispatchToProps 함수와 관련이 있어 보입니다. React에서는 컴포넌트를 랜더링 하는동안 함수가 호출되면 위와 같은 경고 메세지를 내보낸다고 합니다. 따라서 mapDispatchToProps 함수 대신 useDispatch를 사용하는 것으로 해결했습니다.