0

I'm trying to get a bunch of articles from API using axios and useContext hook in React, but getting 'null' as a response. This is the code from "State" file

import React, { useReducer } from "react";
import axios from "axios";
import ArticleContext from "./articleContext";
import articleReducer from "./articleReducer";
import { GET_ARTICLE } from "../types";

const ArticleState = (props) => {
  const initialState = {
    article: null,
  };

  const [state, dispatch] = useReducer(articleReducer, initialState);

  const getArticle = async (id) => {
    try {
      const res = await axios.get(`/articles/${id}`);
      dispatch({ type: GET_ARTICLE, payload: res.data });
    } catch (err) {
      console.log("errrrr");
    }
  };

  return (
    <ArticleContext.Provider
      value={{
        article: state.article,
        getArticle,
      }}
    >
      {props.children}
    </ArticleContext.Provider>
  );
};
export default ArticleState;

This is code from "Reducer"

import { GET_ARTICLE } from "../types";
// eslint-disable-next-line import/no-anonymous-default-export
export default (state, action) => {
  switch (action.type) {
    case GET_ARTICLE:
      return {
        ...state,
        article: action.payload,
      };
    default:
      return state;
  }
};

And finally code from the component, where i' trying to render data from the api call response and getting TypeError: article is null Am i missing something here? The main App component is also wrapped in <ArticleState></ArticleState>.

import React, { useEffect, useContext } from "react";
import ArticleContext from "../../context/article/articleContext";

const Article = () => {
  const articleContext = useContext(ArticleContext);
  const { article, getArticle } = articleContext;
  useEffect(() => {
    getArticle();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <div className="article" key={article.id}>
      <h2 className="article__title">{article.Title}</h2>
      <p className="article__body">{article.preview}</p>
    </div>
  );
};

export default Article;

1 Answer 1

3

You should check if the article has been set before displaying its data.
Add a condition to the component before rendering the article informations:

const Article = () => {
  const articleContext = useContext(ArticleContext);
  const { article, getArticle } = articleContext;

  useEffect(() => {
    getArticle();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  if (!article) {
      return <>Loading article...</>
  }

  return (
    <div className="article" key={article.id}>
      <h2 className="article__title">{article.Title}</h2>
      <p className="article__body">{article.preview}</p>
    </div>
  );
};
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.