0

I have an array of results coming from an API that I called using axios. get(). Then the result is in array and I want to map it into table in react js.

Below is the API fetching data

const [data, getData] = useState([])
    
    useEffect(() => {
        axios.get("http://localhost:4000/api/authentication/history")
        .then(result =>{
        console.log(result.data.result)
        getData(JSON.stringify(result.data.result))
        console.log(data.length)
        })
    }, [])

The line console.log(data.length) returns 0. I dont know why the data is not stored in the data function. That is why when I map {data.map} into it will return error as data.map is not a function. So, is there a simpler way to display and map this array of result into react js table?

Here is the image of the array of result (it is not in json type but in array)

  • 1
    What is `getData`? Is it asynchronous? See also [Is Chrome’s JavaScript console lazy about evaluating objects?](https://stackoverflow.com/questions/4057440/is-chrome-s-javascript-console-lazy-about-evaluating-objects). – Amadan Aug 17 '22 at 08:24
  • oh sorry, forgot to put line which im using useState-> const [data, getData] = useState([]) – andi azamuddin Aug 17 '22 at 08:34
  • 1
    @Oyyou apparently intuited your problems. Naming your _setter_ `getData` was your first mistake :) For the reason why you don't immediately see your update, see [The useState set method is not reflecting a change immediately](https://stackoverflow.com/questions/54069253/the-usestate-set-method-is-not-reflecting-a-change-immediately). – Amadan Aug 17 '22 at 08:38

1 Answers1

1

Update #1

Since posting this (7 hours ago), I tried to do this myself, and realised I completely invented this feature, and callback isn't actually a function of useState

I did some research and came across this very useful function:

const useStateCallback = (initialState) => {
  const [state, setState] = useState(initialState);
  const cbRef = useRef(null); // init mutable ref container for callbacks

  const setStateCallback = useCallback((s, cb) => {
    cbRef.current = cb; // store current, passed callback in ref
    setState(s);
  }, []); // keep object reference stable, exactly like `useState`

  useEffect(() => {
    // cb.current is `null` on initial render,
    // so we only invoke callback on state *updates*
    if (cbRef.current) {
      cbRef.current(state);
      cbRef.current = null; // reset callback after execution
    }
  }, [state]);

  return [state, setStateCallback];
};

Original

I don't know what getData is, but I'll assume it's state, and you have something like this:

const [data, getData] = useStateCallback(); // previously useState

If that's the case, when you call your getData, you can do a callback as the 2nd argument. That callback happens when your state updates successfully:

...
getData(JSON.stringify(result.data.result), () => console.log(data.length));
...

If that's now how you're doing it, then I'd suggest you change whatever you're doing to be in state, and also rename getData to setData

Explanation

When you're calling your getData, you're telling react that you want to update your data? Great! The thing to note is, react doesn't do this update immediately. Instead, it updates it (and other state) in the future, all at the same time.

With that in mind, you pass the callback function as the 2nd argument to tell react what you want to happen once this specific state has been updated

As for getData to setData? That's because the function doesn't return (get) anything, but does set something. Makes your code clearer

Oyyou
  • 610
  • 5
  • 13