React 不重新渲染状态变化?

时间:2021-06-03 08:15:46

标签: javascript reactjs

我目前正在渲染一个页面,其中一堆 Pokemon 排列在单独的“卡片”中。每个神奇宝贝都可以根据状态选择收藏和不收藏,收藏神奇宝贝会使卡片变成粉红色,而不收藏神奇宝贝会将其变回标准灰色。

我希望在单击按钮后立即将页面或 Pokemon 卡重新呈现为正确的颜色,并拥有正确的喜欢或不喜欢的方法,但目前我必须刷新页面才能实现这一点。目前,我的组件 Pokemon 由我的组件 Dashboard 呈现,其中 Dashboard 将绘制 30 个不同的 Pokemon 组件并以类似网格的方式布置它们。所以我想知道这是否可行?这是我的代码:

import React, { useState, useEffect, useContext } from 'react';
import './Pokemon.css';
import Popup from 'reactjs-popup';
import 'reactjs-popup/dist/index.css';
import UserContext from '../../context/userContext';
import { array } from 'prop-types';

import axios from 'axios';


function Pokemon(props) { // Have app.js pass in props of the jsons to here? Then render their names and pictures, and prepare if click
  const [isFav, setIsFav] = useState();
  const { userData, setUserData } = useContext(UserContext); // use userData.user.favPokemon to access the favorite pokemon
  const [error, setError] = useState();
  const [putArr, setPutArr] = useState([...userData.user.favPokemon]);
  // Can use userData.user.favPokemon.find(props.pokemon.name) to search for the pokemon. If found (i.e. not undefined)
  // then render it differently.


  useEffect(() => {
    const found = (element) => element === props.pokemon.name;
    const isFound = (userData.user.favPokemon).some(found);
    setIsFav(isFound);
    if (isFound) {
      const index = userData.user.favPokemon.indexOf(props.pokemon.name);
      const removedFav = putArr;
      removedFav.splice(index, 1);

      setPutArr(removedFav); // array we will be PATCH'ing when we want to unfavorite a pokemon (array - current pokemon)
      // putArr.splice(index, 1); 
    }
    else {
      setPutArr(putArr.concat(props.pokemon.name)); // array we will be PATCH'ing when we want to favorite a pokemon (array + current pokemon)
      // putArr.push(props.pokemon.name) 
    }
  }, [isFav])

  const id = userData.user.id;
  const favOrUnfav = async (e) => { // Patch method to favorite or unfavorite a pokemon
    e.preventDefault();
    try {
      console.log(putArr);
      const updateUser = {id, putArr};
      await axios.patch("http://localhost:5000/users/favorite", updateUser);
    } catch(err) {
      err.response.data.msg && setError(err.response.data.msg)
    }
    setIsFav(!isFav);
  };
    
  const pokeFacts = {
    imageUrl: props.pokemon.sprites.front_default,
    name: props.pokemon.name,
    ability: props.pokemon.abilities[0].ability.name,
    numberMoves: props.pokemon.moves.length,
    type: props.pokemon.types,
    stats: props.pokemon.stats
  }

  return (
    isFav === true ? 
    <div className="Pokemon-card-fav">
      <Popup trigger={<div><img className="Pokemon-card-image" src={pokeFacts.imageUrl} alt="Picture of a pokemon"></img>
      {pokeFacts.name} <button className="favButton" onClick={(e) => {favOrUnfav(e); console.log(isFav)}}>UnFavorite</button></div>} modal>
        <div>
          <p><b>Name</b>: {pokeFacts.name}</p>
          <p><b>Ability</b>: {pokeFacts.ability}</p>
          <p><b>Number of Possible Moves</b>: {pokeFacts.numberMoves}</p>
          <p><b>Type</b>: {pokeFacts.type.map((index) => (index.type.name) + " ")}</p>
          <p><b>Base Stats</b>: {pokeFacts.stats.map((index) => (index.stat.name) + ": " + (index.base_stat) + " ")}</p>
        </div>
      </Popup>
    </div>
    :
    <div className="Pokemon-card">
      <Popup trigger={<div><img className="Pokemon-card-image" src={pokeFacts.imageUrl} alt="Picture of a pokemon"></img>
      {pokeFacts.name} <button className="favButton" onClick={(e) => {favOrUnfav(e); console.log(isFav)}}>Favorite</button></div>} modal>
        <div>
          <p><b>Name</b>: {pokeFacts.name}</p>
          <p><b>Ability</b>: {pokeFacts.ability}</p>
          <p><b>Number of Possible Moves</b>: {pokeFacts.numberMoves}</p>
          <p><b>Type</b>: {pokeFacts.type.map((index) => (index.type.name) + " ")}</p>
          <p><b>Base Stats</b>: {pokeFacts.stats.map((index) => (index.stat.name) + ": " + (index.base_stat) + " ")}</p>
        </div>
      </Popup>
    </div>
  );
}

export default Pokemon;

enter image description here

3 个答案:

答案 0 :(得分:0)

我认为您可以使用 Pokemon 道具渲染 Pokemon 组件,而无需在组件中进行 http 请求。

我的意思是你应该在父组件中做请求并将道具传递给 Pokemon 组件。您可以在父组件中通过单击按钮进行请求并将道具传递给 Pokemon 组件,以便您的组件将被重新渲染。

您可以创建 useCallback 函数,在父组件中执行您的 Pokemon !favorite 并传递给 Pokemon,以便您可以用于更改最喜欢的状态。

答案 1 :(得分:0)

我怀疑 extension Node { @nonobjc public class func fetchRequest() -> NSFetchRequest<Node> { return NSFetchRequest<Node>(entityName: "Node") } @NSManaged public var value: String? @NSManaged public var children: NSSet? @NSManaged public var parent: Node? @objc(addChildrenObject:) @NSManaged public func addToChildren(_ value: Node) @objc(removeChildrenObject:) @NSManaged public func removeFromChildren(_ value: Node) @objc(addChildren:) @NSManaged public func addToChildren(_ values: NSSet) @objc(removeChildren:) @NSManaged public func removeFromChildren(_ values: NSSet) } 没有解析,因此 favOrUnfav 没有执行。

我的建议是在完成后调用 setIsFav 方法,然后设置状态。

.then

答案 2 :(得分:0)

我真的明白了,只需要在 useEffect 中有一个空数组,而不是有 [isFav]!我认为这是有道理的,因为每次安装组件时您都希望这样做,这就是 [] 将要做的。