useEffect does not work when trying to transform Stateful component into Stateless

Asked

Viewed 27 times

0

I have a component that was class-based, and I’m now passing it on to be function-based. The only problem I’m having is that, before, I used the component DidMount() to start the component with some information taken from the backend, and now, when I try to use useEffect to do this, it’s giving as Undefined. I would also like your help to know if I am doing the migration the right way, as I am a beginner in React.

Here’s my Functional Component:

import React, { useState } from 'react'
import axios from 'axios'

import './NewsData.scss'

const baseUrl = 'http://localhost:3001/news'

const NewsData = () => {

    const [list, setList] = useState([])
    const [order, setOrder] = useState('')

    // componentDidMount() {
    //     axios(baseUrl).then(resp => {
    //         this.setState({ list: resp.data })
    //     })
    // }

    useEffect(() => {
        fetch(baseUrl)
            .then(resp => resp.json())
            .then(data => setList({ list: data }))
    })

    const renderCard = () => {
        return list.map((news, index) => {
            return (
                <div className="container" key={index}>
                    <div className="post">
                        <div className="header_post">
                            <img src={news.file} alt="posted-by-user" />
                        </div>

                        <div className="body_post">
                            <div className="post_content">
                                <h1>{news.title}</h1>
                                <p>{news.description}</p>

                                <div className="container_infos">
                                    <div className="postedBy">
                                        <span>author</span>
                                        {news.author}
                                    </div>

                                    <div className="container_tags">
                                        <span>Subject:</span>
                                        <div className="tags">
                                            <ul>
                                                <li>{news.subject}</li>
                                            </ul>
                                        </div>

                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            )
        })
    }

    let displayOrder = renderCard()

    if (order === "older-ones")
        displayOrder = renderCard().sort().reverse()

    const changeSelect = (e) => {
        setOrder({ order: e.target.value })
    }

    return (
        <div className="news">
            <select name="order" className="order-select" onChange={(e) => changeSelect(e)}>
                <option value="new-ones" defaultValue >Order by the older ones</option>
                <option value="older-ones">Order by the new ones</option>
            </select>
            {displayOrder}
        </div>
    )
}

export default NewsData

And here’s my old class-based component:

import React, { Component } from 'react'
import axios from 'axios'

import './NewsData.scss'

const baseUrl = 'http://localhost:3001/news'

class NewsData extends Component {

    state = { list: [], displayOrder: '' }

    componentDidMount() {
        axios(baseUrl).then(resp => {
            this.setState({ list: resp.data })
        })
    }

    renderCard() {
        return this.state.list.map((news, index) => {
            return (
                <div className="container" key={index}>
                    <div className="post">
                        <div className="header_post">
                            <img src={news.file} alt="posted-by-user" />
                        </div>

                        <div className="body_post">
                            <div className="post_content">
                                <h1>{news.title}</h1>
                                <p>{news.description}</p>

                                <div className="container_infos">
                                    <div className="postedBy">
                                        <span>author</span>
                                        {news.author}
                                    </div>

                                    <div className="container_tags">
                                        <span>Subject:</span>
                                        <div className="tags">
                                            <ul>
                                                <li>{news.subject}</li>
                                            </ul>
                                        </div>

                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            )
        })
    }

    alterarSelect(e) {
        this.setState({ displayOrder: e.target.value })
    }

    render() {
        let displayOrder = this.renderCard()

        if (this.state.displayOrder === "older-ones")
            displayOrder = this.renderCard().sort().reverse()

        return (
            <div className="news">
                <select name="order" className="order-select" onChange={(e) => this.alterarSelect(e)}>
                    <option value="new-ones" defaultValue >Order by the older ones</option>
                    <option value="older-ones">Order by the new ones</option>
                </select>
                {displayOrder}
            </div>
        )
    }
}

export default NewsData

Thank you for your attention and help.

1 answer

1


Your problem is placing the list as an object and not as an array.

useEffect(() => {
        fetch(baseUrl)
            .then(resp => resp.json())
            // aqui deve ser um array
            .then(data => setList(data))
})

This array is for two reasons:

  • You initiated the const [list, setList] = useState([]) namely the list will start with an array and to MODIFY this array you will use setList([novoArray])
  • You are using list.map If I was gonna do it the way you put it, you’d have to do it list.list.map after all you put an object in setList
  • 1

    Thank you for the reply :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.