Issue Converting react class components to functional components with state is undefined

117 Views Asked by At

Can life cycles be used in Arrow functions using componentDidMount() and having an error my only response I tried to add a useEffect ? Trying to Converting class components to functional components.
I created a contentful blog in a separate project below and would like to add my blog to my blog.js page in my main project.

Original contentful blog that works.

Blog.js

import React from "react";
import "./App.css";
import { client } from "./client";
import Posts from "./components/blog/Posts";

class App extends React.Component {
  state = {
    articles: [],
  };

  componentDidMount() {
    client
      .getEntries()
      .then((response) => {
        console.log(response);
        this.setState({
          articles: response.items,
        });
      })
      .catch(console.error);
  }

  render() {
    return (
      <div className="App">
        <div className="container">
          <header>
            <div className="wrapper">
              <span>React and Content</span>
            </div>
          </header>
          <main>
            <div className="blog__page">
              <h1 class="blog__page__header">ZILAH MUSIC PUBLISHING NEWS</h1>
              <div className="blogs">
                <div className="wrapper">
                  <Posts posts={this.state.articles} />
                </div>
              </div>
            </div>
          </main>
        </div>
      </div>
    );
  }
}

export default App;

I added a useEffect and now my state is undefined

 useEffect(() => {
    client
      .getEntries()
      .then((response) => {
        console.log(response);
        this.setState({
          articles: response.items,
        });
      })
      .catch(console.error);
  }, []);

I duplicated my previous running pages and would like to include my blog but I have an issue convertingenter image description here

import React, { useEffect, useState } from "react";
import { Link, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { client } from "../../client";
import Posts from "../../components/blog/Posts";

import "./Blog.css";

class App extends React.Component inside an arrow function

const Blog = ({ isAuthenticated }) => {
  if (isAuthenticated) {
    return <Redirect to="/dashboard" />;
  }


useEffect(() => {
        client
          .getEntries()
          .then((response) => {
            console.log(response);
            this.setState({
              articles: response.items,
            });
          })
          .catch(console.error);
      }, []);

  return (
    <React.Fragment>
      <div className="App">
      <div className="container">
          <header>
            <div className="wrapper">
              <span>React and Content</span>
            </div>
          </header>
          <main>
            <div className="blog__page">
              <h1 className="blog__page__header">
                ZILAH MUSIC PUBLISHING NEWS
              </h1>
              <div className="blogs">
                <div className="wrapper">
                  <Posts posts={this.state.articles} />
                </div>
              </div>
            </div>
          </main>
        </div>
      </div>
    </React.Fragment>
  );
};

Bog.propTypes = {
  isAuthenticated: PropTypes.bool,
};

const mapStateToProps = (state) => ({
  isAuthenticated: state.auth.isAuthenticated,
});

export default connect(mapStateToProps)(Blog);
2

There are 2 best solutions below

4
jnpdx On

Function components use the useState hook instead of this.setState and this.state (https://reactjs.org/docs/hooks-state.html).

At the top of your function component, add this (make sure to import useState from 'react' like you did with useEffect):

const Blog = ({ isAuthenticated }) => {
  const [articles, setArticles] = useState([]);
  //... etc

Then, instead of this.setState() use:

setArticles(response.items);

And, in the body:

<div className="wrapper">
  <Posts posts={articles} />
</div>

The title of your post (expected parameter accessToken) seems unrelated to the problem you mention part way through saying that your state is undefined, which is what this answer addresses

6
concepttech On

I updated my code and recieved this error. src\components\layout\Blog.js Line 16:35: React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return? react-hooks/rules-of-hooks Line 18:3: React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return? react-hooks/rules-of-hooks

import React, { useEffect, useState } from "react";
import { Link, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { client } from "../../client";
import Posts from "../../components/blog/Posts";

import "./Blog.css";
import BlogConnect from "./BlogConnect";

const Blog = ({ isAuthenticated }) => {
  if (isAuthenticated) {
    return <Redirect to="/dashboard" />;
  }

  const [articles, setArticles] = useState([]);

  useEffect(() => {
    client
      .getEntries()
      .then((response) => {
        console.log(response);
        setArticles(response.items);
      })
      .catch(console.error);
  }, []);

  return (
    <React.Fragment>
      <div className="App">
        <div className="container">
          <header>
            <div className="wrapper">
              <span>React and Content</span>
            </div>
          </header>
          <main>
            <div className="blog__page">
              <h1 className="blog__page__header">
                ZILAH MUSIC PUBLISHING NEWS
              </h1>
              <div className="blogs">
                <div className="wrapper">
                  <Posts posts={articles} />
                </div>
              </div>
            </div>
          </main>
        </div>
      </div>
    </React.Fragment>
  );
};

Blog.propTypes = {
  isAuthenticated: PropTypes.bool,
};

const mapStateToProps = (state) => ({
  isAuthenticated: state.auth.isAuthenticated,
});

export default connect(mapStateToProps)(Blog);