简体   繁体   English

React Hooks:useState with onClick 只更新第二次点击按钮?

[英]React Hooks: useState with onClick only updating the SECOND time button is clicked?

Edit: forgot an important part - this is noticeable if you click the button next to Jeff A. Menges and check the console log.编辑:忘记了一个重要的部分 - 如果您单击 Jeff A. Menges 旁边的按钮并检查控制台日志,这会很明显。

The important part of the code is the "setFullResults(cardResults.data.concat(cardResultsPageTwo.data))" line in the onClick of the button code.代码的重要部分是按钮代码的onClick中的“setFullResults(cardResults.data.concat(cardResultsPageTwo.data))”行。 I think it SHOULD set fullResults to whatever I tell it to... except it doesn't work the first time you click it.我认为它应该将 fullResults 设置为我告诉它的任何内容......除非它在你第一次点击它时不起作用。 Every time after, it works, but not the first time.每次之后,它都有效,但不是第一次。 That's going to be trouble for the next set, because I can't map over an undefined array, and I don't want to tell users to just click on the button twice for the actual search results to come up.这对下一组来说会很麻烦,因为我无法映射未定义的数组,而且我不想告诉用户只需单击按钮两次即可出现实际搜索结果。

I'm guessing useEffect would work, but I don't know how to write it or where to put it.我猜 useEffect 会起作用,但我不知道如何编写它或将它放在哪里。 It's clearly not working at the top of the App functional component, but anywhere else I try to put it gives me an error.它显然不能在 App 功能组件的顶部工作,但是我尝试将它放在其他任何地方都会给我一个错误。

I've tried "this.forceUpdate()" which a lot of places recommend as a quick fix (but recommend against using - but I've been trying to figure this out for hours), but "this.forceUpdate()" isn't a function no matter where I put it.我已经尝试过“this.forceUpdate()”,很多地方都推荐它作为快速修复(但建议不要使用——但我已经尝试了几个小时来解决这个问题),但是“this.forceUpdate()”不是无论我把它放在哪里,都不是一个函数。

Please help me get this button working the first time it's clicked on.请帮助我让这个按钮在第一次被点击时起作用。


import React, { useState, useEffect } from "react";

const App = () => {

  let artistData = require("./mass-artists.json");

  const [showTheCards, setShowTheCards] = useState();
  const [fullResults, setFullResults] = useState([]);

  useEffect(() => {
    setFullResults();
  }, []);

  let artistDataMap = artistData.map(artistName => {
    //console.log(artistName);
    return (
      <aside className="artist-section">
        <span>{artistName}</span>
        <button
          className="astbutton"
          onClick={ function GetCardList() {
            fetch(
              `https://api.scryfall.com/cards/search?unique=prints&q=a:"${artistName}"`
            )
              .then(response => {
                return response.json();
              })
              .then((cardResults) => {
                console.log(cardResults.has_more)
                if (cardResults.has_more === true) {
                fetch (`https://api.scryfall.com/cards/search?unique=prints&q=a:"${artistName}"&page=2`)
                .then((responsepagetwo) => {
                  return responsepagetwo.json();
                })
                .then(cardResultsPageTwo => {
                  console.log(`First Results Page: ${cardResults}`)
                  console.log(`Second Results Page: ${cardResultsPageTwo}`)
                  setFullResults(cardResults.data.concat(cardResultsPageTwo.data))
                  console.log(`Full Results: ${fullResults}`)
                })
                }
                setShowTheCards(
                  cardResults.data
                  .filter(({ digital }) => digital === false)
                  .map(cardData => {
                    if (cardData.layout === "transform") {
                      return (
                        //TODO : Transform card code
                        <span>Transform Card (Needs special return)</span>
                      )
                    }
                    else if (cardData.layout === "double_faced_token") {
                      return (
                        //TODO: Double Faced Token card code
                        <span>Double Faced Token (Needs special return)</span>
                      )
                    }
                    else {
                      return (
                        <div className="card-object">
                          <span className="card-object-name">
                          {cardData.name}
                          </span>
                          <span className="card-object-set">
                          {cardData.set_name}
                          </span>
                          <img
                          className="card-object-img-sm"
                          alt={cardData.name}
                          src={cardData.image_uris.small}
                          />
                        </div>
                      )
                    }
                  })
                )
              });
          }}
        >
          Show Cards
        </button>

      </aside>
    );
  });

  return (
    <aside>
      <aside className="artist-group">
      {artistDataMap}
      </aside>
      <aside className="card-wrapper">
      {showTheCards}
      </aside>
    </aside>
  );
};

export default App;

CodesAndBox: https://codesandbox.io/embed/compassionate-satoshi-iq3nc?fontsize=14 CodesAndBox: https ://codesandbox.io/embed/compassionate-satoshi-iq3nc ? fontsize =14

You can try refactoring the code like for onClick handler have a synthetic event.您可以尝试重构代码,例如 onClick 处理程序具有合成事件。 Add this event Listener as part of a class.将此事件侦听器添加为类的一部分。 Use arrow function so that you need not bind this function handler inside the constructor.使用箭头函数,这样你就不需要在构造函数中绑定这个函数处理程序。 After fetching the data try to set the state to the result and use the state to render the HTML mark up inside render method.获取数据后,尝试将状态设置为结果,并使用该状态在 render 方法中呈现 HTML 标记。 And when I run this code, I have also seen one error in console that child elements require key attribute.当我运行此代码时,我还在控制台中看到了一个错误,即子元素需要 key 属性。 I have seen you are using Array.prototype.map inside render method, but when you return the span element inside that try to add a key attribute so that when React diffing algorithm encounters a new element it reduces the time complexity to check certain nodes with this key attribute.我已经看到您在渲染方法中使用 Array.prototype.map,但是当您返回内部的 span 元素时,尝试添加一个关键属性,以便当 React diffing 算法遇到新元素时,它会降低检查某些节点的时间复杂度这个关键属性。

useEffect(() => {
   // call the functions which depend on fullResults here
   setFullResults();
}, [fullResults])

// now it will check whether fullResults changed, if changed than call functions inside useEffect which are depending on fullResults //现在它会检查是否fullResults改变,如果改变不是内部useEffect通话功能这是根据fullResults

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM