Home > Net >  React hooks not showing correct data when component is rendered
React hooks not showing correct data when component is rendered

Time:12-29

I have created a hook in a component as below.

useEffect(() => {
    axios
      .get("http://127.0.0.1:5000/v1/matches")
      .then((response) => {
        getStatusCode(response.data.code);
        console.log("responseCode",responseCode);
        getMatchdata(response.data.result);
        setInfo(<MatchData responseCode={responseCode} matchdata={matchdata} />);
      })
      .catch((error) => console.log(error));
      
  },[]);

This is a state function used in the above effect

 const [info, setInfo] = useState();

I expected the above useEffect should return me some data in the below block

<div> {info} </div>

but it is showing wrong data, whereas I have created another function to trigger on Refresh button as

function refresh() {
    setInfo(<MatchData responseCode={responseCode} matchdata={matchdata} />);
  }

this function is returning me correct data. I want to create a functionality that will dynamically update the div element with change in state of {info}, by default when the page is loaded first, it should fetch data from the endpoint used here only. I'm new to React. Where I'm going wrong and how do I achieve it?

CodePudding user response:

I don't want to say this is wrong, but this seems like an atypical approach from what I've seen in the wild. Specifically I am talking about storing a JS/JSX or TS/TSX element in a state object. I have more commonly seen a value stored in that type of variable and that value changing when necessary via the set dispatch function. Then the state object is passed to the component who needs it to do something. In react, when the value of that state object changes, it will cause the component who uses it to re-render. If I were coding this, this is what my code would look like.

const [info, setInfo] = useState();

const getData = () => {
  axios
    .get("http://127.0.0.1:5000/v1/matches")
    .then((response) => {
      setInfo(response.json())
    })
    .catch((error) => console.log(error));
}

const divComponent = ({info}) => (
  <div>
    <p>{info.data.code}</p>
    <p>{info.data.result}</p>
  </div>
)

const refreshButton = () => (
  <button onClick(()=>getData())>Refresh</button>
)

Unless you only specifically want something to happen once at component mount, you would not use useEffect() like you did in your code. If the decision to refresh were coming from an external object with state instead of the refresh button, you could add that object whose state changes to the dependency array of the useEffect function. This would cause the refresh to run any time that object's state value changes. In the code above, getData() (which might need to be async) will only run when called. Then you have a component called divComponent which is expecting info to have value. When rendering this component you would want a null check like I coded below. Finally the refreshButton component will call getData() when it is clicked.

Then in your code that renders this, I would have something like this:

<>
  {info ? <divComponent info={info} /> : <p>There is no info</p>}
  <refreshButton />
</>

The code above will check if the state object info has value, and if it does it will render the divComponent with your data values. If it does not, instead it will show the p tag explaining that there is no data. Either way it will render the refreshButton, which would run the getData() function again when clicked.

** EDIT ** Based on your comment, here is another approach so you can have a value on page load and update when necessary:

import {useState, useEffect} from "react";

const [info, setInfo] = useState();

const getData = () => {
  axios
    .get("http://127.0.0.1:5000/v1/matches")
    .then((response) => {
      setInfo(response.json())
    })
    .catch((error) => console.log(error));
}

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

const divComponent = ({info}) => (
  <div>
    <p>{info.data.code}</p>
    <p>{info.data.result}</p>
  </div>
)

const refreshButton = () => (
  <button onClick(()=>getData())>Refresh</button>
)

export const Page = () => (
  <>
    {info ? <divComponent info={info} /> : <p>There is no info</p>}
    <refreshButton />
  </>
);

CodePudding user response:

your method is quite complex. I believe you need to add your MatchData Component Inside the div in this way.Also Don't Need To Call State Method setInfo() in useEffect hook.Only responseCode and matchdata Needed that is already adjusted by you in useEffect Hook.

Code Picture

  • Related