C
C
chatterbox7772020-09-26 10:50:13
JavaScript
chatterbox777, 2020-09-26 10:50:13

Data is not forwarded to the component due to idle useEffect'a?

Hello, dear, I ask for help ... I understand hooks .... the problem is that when I forward the state of the parent component (spawn comp => App) (in my case, I forward selectedPokemon) to the child (child comp. Pokemon) the following errors pop up:
1) Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
2) Uncaught TypeError: Cannot read property 'sprites' of undefined ( at Pokemon (Pokemon.jsx:12) )

I read and understood that the error is that useEffect does not unsubscribe and a memory leak occurs .. it seems that I wrote a condition in useEffect so that it works as it should, but it doesn’t work as a result ... tell me what is my mistake? thank!

App.jsx

import React, { useEffect } from "react";
import "./App.css";
import { connect } from "react-redux";
import * as axios from "axios";
import { Button, Card } from "react-bootstrap";
import { useState } from "react";
import { BrowserRouter, NavLink, Route } from "react-router-dom";
import Pokemon from "./Pokemon/Pokemon";

function App({ count }) {
  const [pokemons, setPokemons] = useState([]);
  const [selectedPokemon, setSelectedPokemon] = useState({});
  console.log("pokemons =>", pokemons);
  useEffect(() => {
    let isSubscribed = true;

    axios.get("https://pokeapi.co/api/v2/pokemon").then((response) => {
      if (isSubscribed) {
        let pokemons = response.data.results;
        setPokemons(pokemons);
      }
    });

    return () => (isSubscribed = false);
  }, []);

  let getPokemonInfo = (pokemon, id, url) => {
    // let pokemonName = pokemon;
    // let pokemonId = id;
    axios.get(url).then((response) => {
      const serverPokemonInfo = response.data;
      setSelectedPokemon({ ...pokemon, id, serverPokemonInfo });
    });
  };
  console.log("выбранный покемон =>", selectedPokemon);
  return (
    <BrowserRouter>
      <div className="App">
        <div className="container">
          <div className="row">
            {pokemons.map((pokemon, index) => (
              <div key={index} className="col-lg-4 mt-lg-4">
                <Card style={{ width: "18rem" }}>
                  <Card.Img
                    variant="top"
                    src="https://htstatic.imgsmail.ru/pic_original/14dda5f3f885a7304a22af4635aa54b0/1658985/"
                  />
                  <Card.Body>
                    <Card.Title>{pokemon.name}</Card.Title>
                    <Card.Text>
                      Some quick example text to build on the card title and
                      make up the bulk of the card's content.
                    </Card.Text>
                    <NavLink to={`/pokemon/${index + 1}`}>
                      {" "}
                      <Button
                        onClick={() =>
                          getPokemonInfo(pokemon, index + 1, pokemon.url)
                        }
                        variant="primary"
                      >
                        Get more info
                      </Button>
                    </NavLink>
                  </Card.Body>
                </Card>
                <Route path={`/pokemon/${index + 1}`}>
                  <Pokemon
                    selectedPokemon={selectedPokemon}
                    index={index + 1}
                  />
                </Route>
              </div>
            ))}
          </div>
        </div>
      </div>
    </BrowserRouter>
  );
}

const mapStateToProps = (state, ownProps) => {
  console.log(state);
  return { count: state.count };
};

export default connect(mapStateToProps)(App);


Pokemon.jsx

import React from "react";
import { Card } from "react-bootstrap";
import styles from "./Pokemon.module.css";

const Pokemon = (props) => {
  console.log(props);
  return (
    <div className={styles.pokemonInfo}>
      <Card>
        <Card.Img
          variant="top"
          src={props.selectedPokemon.serverPokemonInfo.sprites.front_default} //  Pokemon.jsx 12
        />
        <Card.Body>
          <Card.Text>
            Some quick example text to build on the card title and make up the
            bulk of the card's content.
          </Card.Text>
        </Card.Body>
      </Card>
      <br />
      <Card>
        <Card.Body>
          <Card.Text>
            Some quick example text to build on the card title and make up the
            bulk of the card's content.
          </Card.Text>
        </Card.Body>
        <Card.Img variant="bottom" src="holder.js/100px180" />
      </Card>
    </div>
  );
};

export default Pokemon;

Answer the question

In order to leave comments, you need to log in

3 answer(s)
D
Dmitry, 2015-11-28
@Viccc

option at css jsfiddle.net/soledar10/9o63wehc

A
Alexander, 2020-09-26
@Seasle

1. In the returned function useEffect, cancel the axios request.
2. What does it look like selectedPokemon?

C
chatterbox777, 2020-09-26
@chatterbox777

1. In the return function of useEffect, cancel the axios request.
how to do it? 0o and plus, I think, having already reconsidered my problem, that useEffect has nothing to do with it, since the data comes from the getPokemonInfo function ... most likely there is something wrong with asynchrony .. but for some reason, the topic of asynchrony is very difficult for me

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question