0

I want to display data from an API, which user input will be part of the API URL. To be more precise, the goal is to let user enter an ETH wallet address, and display the NFT assets this wallet has, using Opensea API.

My problem is that the data is fetched and displayed before user submit input. (It's also a valid api url but not the data I want to fetch).

How to fix this issue? I think one way is to keep a boolean state of submitted, and display only if it is true. But this way it makes the api call regardless, although not rendered. Is there a better way? Does it matter what I set as the initial state for owner?

My guess is that there needs an async function, and the api fetch is callback. Trigger is the user input event. I'm not sure how to construct this.

Below is my code.

import { useState, useEffect } from "react";

// example user input:  0x147412d494731cbb91dbb5d7019464a536de04dc

function App() {
  const [data, setData] = useState({ assets: [] });
  const [enteredWallet, setEnteredWallet] = useState("");
  const [owner, setOwner] = useState("");

  const walletChangeHandler = (event) => {
    setEnteredWallet(event.target.value);
  };

  const submittedHandler = (event) => {
    event.preventDefault();
    setOwner(enteredWallet);
    console.log(enteredWallet);
  };

  useEffect(() => {
    fetch(
      `https://api.opensea.io/api/v1/assets?owner=${owner}&order_direction=desc&offset=0&limit=10`
    )
      .then((res) => {
        return res.json();
      })
      .then((data) => {
        setData(data);
      });
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        <h3>Show me assets in this wallet</h3>
        <form onSubmit={submittedHandler}>
          <input
            placeholder="wallet address"
            value={enteredWallet}
            onChange={walletChangeHandler}
          />
          <button>Submit</button>
        </form>
        <div>
          {data.assets.map((i, index, k) => (
            <li key={index}>{i.name}</li>
          ))}
        </div>
      </header>
    </div>
  );
}

export default App;

p.s. I know this fetch api call is not the best approach. it's just for my exercise.

On a separate note, i also got a warning message "react Hook useEffect has a missing dependency: 'owner'. Either include it or remove the dependency array react-hooks/exhaustive-deps" Any clue?

somniumm
  • 115
  • 1
  • 10
  • Regarding missing dependency, take a look here https://stackoverflow.com/questions/55840294/how-to-fix-missing-dependency-warning-when-using-useeffect-react-hook and here https://overreacted.io/a-complete-guide-to-useeffect/ – Mangs Oct 27 '21 at 14:57

1 Answers1

0

It could look something like

const [data, setData] = useState()
const [owner, setOwner] = useState()

useEffect(() => {
  if(owner){
    fetch(...).then(setData)
  }
}, [owner])

return data ? <>something with data goes here</> : <>Loading...</>
pguardiario
  • 53,827
  • 19
  • 119
  • 159