Jens Olsson
Jens Olsson

Reputation: 65

ReactJs useState .map() is not a function

I am trying to understand how the useState and useEffect hooks works in ReactJs.

I get the error message

.map() is not a function

when attempting to display data in a table.

const [posts, setPosts] = useState([]);

useEffect(() => {
    const alarmService = new AlarmService();
    const response = alarmService.getData();
    setPosts(response)
}, [])

return (
    <table className="table">
        <tbody>
        {posts.map(data => (
            <tr key={data.id}>
                <td>
                    <div className="row">
                        {data.name}
                    </div>
                </td>
                <td className="custom" >
                    <button
                        className="btn btn-danger btn-sm"
                        onClick={() => this.handleDelete(data)}
                    >
                        Delete
                    </button>
                </td>
            </tr>
        ))}
        </tbody>
    </table>
);

I assume the issue is in my useEffect, as I am not sure what to do with the response.

SOLVED

I looked into these examples: https://www.robinwieruch.de/react-hooks-fetch-data/

The trick was to create a async function within the useEffect. Like this:

useEffect(() => {
    async function test() {
       const alarmService = new AlarmService();
       const response = await alarmService.getData();
       console.log(response);
       setPosts(response)
    }
    test();
}, []);

Thank you to everyone who took their time to respond and help out!

Upvotes: 2

Views: 3382

Answers (2)

Naina Dhawani
Naina Dhawani

Reputation: 1

Yes, you are right. The problem is in the way we are updating state, i.e in useEffect method. While we are updating state, setPosts doesn't identifies if the posts is an array and updates state as simple object. Hence, you see the error.

You can find similar scenario in the codesandbox, when I am trying to add response in posts https://codesandbox.io/s/ecstatic-flower-lq2r1.

Please uncomment the fix in codesandbox to see things working.

Upvotes: 0

Noob
Noob

Reputation: 2807

I think the problem here is that alarmService.getData is asynchronous and you are not dealing properly with that. That's why you get Promise pending, and you can not map over posts.

useEffect(() => {
    const alarmService = new AlarmService();
    alarmService.getData().then(response => response.json()).then(data =>setPosts(data))    

}, []) 

This should fix your problem.

Upvotes: 1

Related Questions