Apollo GraphQL loading query - next.js

I am using Apollo GraphQL to fetch posts to populate a next js project.
The code I currently have works but I would like to implement the loading state of useQuery instead of what I have below.
This is the index (Posts page if you will)
import Layout from "../components/Layout";
import Post from "../components/Post";
import client from "./../components/ApolloClient";
import gql from "graphql-tag";
const POSTS_QUERY = gql`
query {
posts {
nodes {
title
slug
postId
featuredImage {
sourceUrl
}
}
}
}
`;
const Index = props => {
const { posts } = props;
return (
<Layout>
<div className="container">
<div className="grid">
{posts.length
? posts.map(post => <Post key={post.postId} post={post} />)
: ""}
</div>
</div>
</Layout>
);
};
Index.getInitialProps = async () => {
const result = await client.query({ query: POSTS_QUERY });
return {
posts: result.data.posts.nodes
};
};
export default Index;
Then it fetches an individual Post
import Layout from "../components/Layout";
import { withRouter } from "next/router";
import client from "../components/ApolloClient";
import POST_BY_ID_QUERY from "../queries/post-by-id";
const Post = withRouter(props => {
const { post } = props;
return (
<Layout>
{post ? (
<div className="container">
<div className="post">
<div className="media">
<img src={post.featuredImage.sourceUrl} alt={post.title} />
</div>
<h2>{post.title}</h2>
</div>
</div>
) : (
""
)}
</Layout>
);
});
Post.getInitialProps = async function(context) {
let {
query: { slug }
} = context;
const id = slug ? parseInt(slug.split("-").pop()) : context.query.id;
const res = await client.query({
query: POST_BY_ID_QUERY,
variables: { id }
});
return {
post: res.data.post
};
};
export default Post;
Whenever I have tried to use the useQuery with '#apollo/react-hooks' I always end up with a data.posts.map is not a function.

When you use useQuery, you should not destructure the data like result.data.posts.nodes because the data field will be undefined and loading is true for the first time calling. That why you got an error data.posts.map is not a function. Then if your query fetch data successfully, the loading field will be false.
You can try it:
import Layout from "../components/Layout";
import Post from "../components/Post";
import client from "./../components/ApolloClient";
import { useQuery } from "#apollo/react-hooks"
import gql from "graphql-tag";
const POSTS_QUERY = gql`
query {
posts {
nodes {
title
slug
postId
featuredImage {
sourceUrl
}
}
}
}
`;
const Index = props => {
const { posts } = props;
const { loading, error, data } = useQuery(POSTS_QUERY);
if (loading) return <div>Loading...</div>
if (error) return <div>Error</div>
return (
<Layout>
<div className="container">
<div className="grid">
{data.posts.nodes.length
? data.posts.nodes.map(post => <Post key={post.postId} post={post} />)
: ""}
</div>
</div>
</Layout>
);
};

Related

Component is being rendered twice in SSG page in Next.js

I'm currently trying using utterances, which is a github-based open source for comments.
I'm using utterances in my SSG page. Therefore, I'm using client side rendering for getting the utterances component.
Here is the code.
// blog/[id].tsx
/* eslint-disable react/no-danger */
import axios from 'axios';
import { dateFormat } from '_Utils/Helper';
import MarkdownRenderer from '_Components/MarkdownRenderer';
import Comment from '_Components/Comment';
import styles from './blog.module.scss';
const Article = ({ article }: any) => {
return (
<div className={styles.container}>
<div className={styles.header}>
<p className={styles.tag}>{article.data.attributes.tag.data.attributes.tag}</p>
<h1>{article.data.attributes.title}</h1>
<p className={styles.publishedDate}>Published at {dateFormat(article.data.attributes.publishedAt)}</p>
</div>
<main
>
<MarkdownRenderer markdown={article.data.attributes.content} />
<Comment />
</main>
</div>
);
};
export async function getStaticPaths() {
const articlePaths: any = await axios.get(`${process.env.NEXT_PUBLIC_BASE_URL}/api/articles/?populate[0]=*`);
const paths = articlePaths.data.data.map((path: any) => ({
params: { id: `${path.id}` },
}));
return { paths, fallback: false };
}
export async function getStaticProps(ctx: any) {
const { params } = ctx;
const { id } = params;
const article = await axios.get(
`${process.env.NEXT_PUBLIC_BASE_URL}/api/articles/${id}?populate[1]=tag&populate[0]=thumbnail`
);
return {
props: { article: article.data },
};
}
export default Article;
// Comment
const Comment = () => {
return (
<section
style={{ height: '350px', width: '100%' }}
ref={(elem) => {
if (!elem) {
return;
}
const scriptElem = document.createElement('script');
scriptElem.src = 'https://utteranc.es/client.js';
scriptElem.async = true;
scriptElem.setAttribute('repo', 'usernamechiho/Cobb-dev-blog');
scriptElem.setAttribute('issue-term', 'title');
scriptElem.setAttribute('theme', 'github-light');
scriptElem.setAttribute('label', 'comment');
scriptElem.crossOrigin = 'anonymous';
elem.appendChild(scriptElem);
}}
/>
);
};
export default Comment;
and the result
I was wondering why it happens and tried dynamic import with ssr: false.
However, there was nothing but the same.
Is there anything I can look for to get through this?

Nextjs Build fail on Vercel

I'm trying to deploy my NextJs app (using GraphCMS) on Vercel. When I build the app on my computer it works fine, I can build and run the app locally but once I try to deploy the same exact app on Vercel it crash with this error
TypeError: Cannot read properties of undefined (reading 'document')
at Object.parseRequestExtendedArgs (/vercel/path0/node_modules/graphql-request/dist/parseArgs.js:37:25)
at /vercel/path0/node_modules/graphql-request/dist/index.js:422:42
at step (/vercel/path0/node_modules/graphql-request/dist/index.js:63:23)
at Object.next (/vercel/path0/node_modules/graphql-request/dist/index.js:44:53)
at /vercel/path0/node_modules/graphql-request/dist/index.js:38:71
at new Promise ()
at __awaiter (/vercel/path0/node_modules/graphql-request/dist/index.js:34:12)
at request (/vercel/path0/node_modules/graphql-request/dist/index.js:418:12)
at getPosts (/vercel/path0/.next/server/chunks/104.js:1143:82)
at getStaticPaths (/vercel/path0/.next/server/pages/post/[slug].js:98:86)
Build error occurred
Error: Failed to collect page data for /post/[slug]
at /vercel/path0/node_modules/next/dist/build/utils.js:959:15
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
type: 'Error'
}
error Command failed with exit code 1.
I don't understand where this is coming from.
pages/post/[slug].js
import React from "react";
import { useRouter } from "next/router";
import {
PostDetail,
Categories,
PostWidget,
Author,
Comments,
CommentsForm,
Loader,
} from "../../components";
import { getPosts, getPostDetails } from "../../services";
import { AdjacentPosts } from "../../sections";
const PostDetails = ({ post }) => {
const router = useRouter();
if (router.isFallback) {
return <Loader />;
}
return (
<>
<div className="container mx-auto px-10 mb-8">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12">
<div className="col-span-1 lg:col-span-8">
<PostDetail post={post} />
<Author author={post.author} />
<AdjacentPosts slug={post.slug} createdAt={post.createdAt} />
<CommentsForm slug={post.slug} />
<Comments slug={post.slug} />
</div>
<div className="col-span-1 lg:col-span-4">
<div className="relative lg:sticky top-8">
<PostWidget
slug={post.slug}
categories={post.categories.map((category) => category.slug)}
/>
<Categories />
</div>
</div>
</div>
</div>
</>
);
};
export default PostDetails;
// Fetch data at build time
export async function getStaticProps({ params }) {
const data = await getPostDetails(params.slug);
return {
props: {
post: data,
},
};
}
// Specify dynamic routes to pre-render pages based on data.
// The HTML is generated at build time and will be reused on each request.
export async function getStaticPaths() {
const posts = await getPosts();
return {
paths: posts.map(({ node: { slug } }) => ({ params: { slug } })),
fallback: false,
};
}
here is the Graphql query getPosts
export const getPosts = async () => {
const query = gql`
query MyQuery {
postsConnection {
edges {
cursor
node {
author {
bio
name
id
photo {
url
}
}
createdAt
slug
title
excerpt
displayedDate
featuredImage {
url
}
categories {
name
slug
}
}
}
}
}
`;
const result = await request(graphqlAPI, query);
return result.postsConnection.edges;
};
getPostDetails
export const getPostDetails = async (slug) => {
const query = gql`
query GetPostDetails($slug: String!) {
post(where: { slug: $slug }) {
title
excerpt
featuredImage {
url
id
}
author {
name
bio
photo {
url
}
}
createdAt
slug
content {
raw
}
categories {
name
slug
}
displayedDate
}
}
`;
const result = await request(graphqlAPI, query, { slug });
return result.post;
};
I really don't understand why I can build it locally but not en Vercel, Thanks
Tried to modify queries, turn off fallback and others things that did not work

Nextjs dyanmic router callback sometimes undefined

here is my folder stucture
shop
- [categorySlug]
- [productSlug]
- index.tsx
- index.tsx
index.tsx
graphql calling will be
/shop/shoes/nike-1
/shop/jersey/jersey-1
[categorySlug] index.tsx
export function ShopCategoryComponent({ products }): JSX.Element {
const { query } = useRouter();
const router = useRouter();
const categorySlug = hasCategorySlug(query) ? query.categorySlug : undefined;
const viewProductDeatails = useCallback(
(productSlug) => {
router.push(`/shop/${categorySlug}/${productSlug}`);
},
[router]
);
return (
<section>
{products.map((product) => (
<div
key={`${product.id}`}
onClick={() => viewProductDeatails(product.slug)}
>
<h3>{product.name}</h3>
<h3>{product?.$on['SimpleProduct'].price()}</h3>
<img src={product?.$on['SimpleProduct'].image.sourceUrl()} />
</div>
))}
</section>
);
}
export default function ShopCategory() {
const { useQuery } = client;
const { query } = useRouter();
const { products } = useQuery();
const categorySlug = hasCategorySlug(query) ? query.categorySlug : undefined;
const generalSettings = useQuery().generalSettings;
const setProducts = products({
where: {
categoryIn: categorySlug,
},
}).nodes;
return (
<React.Fragment>
<Menu />
<main className='content content-single'>
<ShopCategoryComponent products={setProducts} />
</main>
<Footer copyrightHolder={generalSettings.title} />
</React.Fragment>
);
}
when i click on the image it will then go to the productSlug page to show single product detail, it work sometimes, sometimes it will be undefined, like this.i wonder where i did wrong to cause this ?
/shop/shoes/undefined
it happen because of re-hydration and the categorySlug and productSlug have not get slug and it show undefined. also i mess up my variable categorySlug.
1.change
const categorySlug = hasCategorySlug(query) ? query.categorySlug : undefined;
to
const categorySlug = query.categorySlug
2.add
export function ShopCategoryComponent({ products }): JSX.Element {
const { query, isReady } = useRouter();
const categorySlug = query.categorySlug;
// pre-render page check, show loading if data havet get it.
if (!isReady) {
return (
<div>
<h1>Loading...</h1>
</div>
);
}
}
now everything work fine now. thanks user8566930

An Reference Error is occured at "#polkadot/extension-dapp/bundle.js"

I tried to implement a simple UI for smart contracts using polkadot.js in the next.js framework.
The content of the WEB UI is a simple one that calls the Flipper contract, which is famous for the sample contract of the substrate.
When compiling, the following error is output. Can you tell me how to solve it?
Souce Code:
import { useEffect, useState } from "react";
import {
web3Accounts,
web3Enable,
web3FromSource,
} from "#polkadot/extension-dapp";
import { InjectedAccountWithMeta } from "#polkadot/extension-inject/types";
const Home = () => {
const [allAccount, setAllAccount] = useState<InjectedAccountWithMeta[]>([]);
const getAccounts = async () => {
const extensions = await web3Enable("my cool dapp");
if (extensions.length === 0) {
return;
}
const allAccounts = await web3Accounts();
setAllAccount(allAccounts);
};
useEffect(() => {
getAccounts();
}, []);
return (
<>
<div>
{typeof allAccount !== "undefined"
? allAccount.map((account) => {
return (
<div key={account.address}>
<div className="font-bold mb-2 text-white">
{account.address}
</div>
</div>
);
})
: ""}{" "}
</div>
</>
);
};
export default Home;
Error Information:
> Build error occurred
ReferenceError: window is not defined
at file:///Users/shin.takahashi/develop/substrate/flipper_frontend/fillper_frontend/node_modules/#polkadot/extension-dapp/bundle.js:10:13
at ModuleJob.run (node:internal/modules/esm/module_job:175:25)
at async Loader.import (node:internal/modules/esm/loader:178:24)
at async importModuleDynamicallyWrapper (node:internal/vm/module:437:15) {
type: 'ReferenceError'
}
This issue occurs because next.js is a framework for server-side rendering.
In order to avoid this problem, it is necessary to control not to execute
server-side rendering for the relevant part.
Componentize the part that gets account information from the relevant Extension.
Adopt dynamic import when using this component and set server-side rendering to off.
component sample code:
import { useEffect, useState } from "react";
import { web3Accounts, web3Enable } from "#polkadot/extension-dapp";
import { InjectedAccountWithMeta } from "#polkadot/extension-inject/types";
const Extention = () => {
const [allAccount, setAllAccount] = useState<InjectedAccountWithMeta[]>([]);
const getAccounts = async () => {
const extensions = await web3Enable("my cool dapp");
if (extensions.length === 0) {
return;
}
const allAccounts = await web3Accounts();
setAllAccount(allAccounts);
};
useEffect(() => {
getAccounts();
}, []);
return (
<>
<div>
{typeof allAccount !== "undefined"
? allAccount.map((account) => {
return (
<div key={account.address}>
<div className="font-bold mb-2 text-white">
{account.address}
</div>
</div>
);
})
: ""}{" "}
</div>
</>
);
};
export default Extention;
Calling component sample code:
import dynamic from "next/dynamic";
import { useState } from "react";
const Extention = dynamic(() => import("../component/extention"), {
ssr: false,
});
const Home = () => {
const [showExtention, setShowExtention] = useState(false);
return (
<>
<button onClick={() => setShowExtention(true)}>show extention</button>
{showExtention == true && <Extention></Extention>}
</>
);
};
export default Home;

Trying to create a dynamic link with API and React router, console is showing [object%20Object].json 404?

I'm currently working on a site that pulls Reddit data from different subreddits to show recipes, you can toggle between 3 different ones. That part works fine! I'm able to pull the list of posts from each subreddit, but now I'm trying to make it so when you click a button, it routes you to post details where it'll show the post and comments. I have to do another API call to get that information.
Somewhere along the way, it's getting messed up and it's showing "xhr.js:210 GET https://www.reddit.com/r/recipes/comments/[object%20Object].json 404:" It's a dynamic route, so there are two different parameters I'm trying to use. I did try and console log the parameter for ID(the one showing up as [object object] and it shows up fine by itself and is not an object from what I can tell.
Please see some of the code below where I think things could be going wrong. I'm guessing it's the API call because when I console log it, it only shows the subreddit as an arg but not sure..
redditAPI.js:
import axios from 'axios';
export default axios.create({
baseURL:"https://www.reddit.com/r/"
})
store.js:
import {configureStore} from '#reduxjs/toolkit';
import postReducer from './posts/postSlice';
export const store = configureStore({
reducer: {
posts: postReducer
}
});
postSlice.js:
import {createSlice, createAsyncThunk} from '#reduxjs/toolkit';
import redditApi from '../../common/api/redditApi';
import { redditDetails } from '../../common/api/redditApi';
export const fetchAsyncPosts = createAsyncThunk('posts/fetchAsyncPosts', async (subreddit) => {
const response = await redditApi.get(subreddit)
return response.data.data.children;
});
export const fetchAsyncPostsDetail = createAsyncThunk('posts/fetchAsyncPostsDetail', async (sub, postID) => {
const response = await redditApi.get(`${sub}/comments/${postID}.json`)
return response.data.data.children;
});
const initialState = {
posts: [],
selectedSubreddit: 'recipes.json',
selectedPost: []
}
const postSlice = createSlice({
name: "posts",
initialState,
reducers: {
addPosts: (state, { payload }) => {
state.posts = payload;
},
addSelectedPost: (state, {payload}) => {
state.selectedPost = payload;
},
setSelectedSubreddit(state, action) {
state.selectedSubreddit = action.payload;
}
},
extraReducers: {
[fetchAsyncPosts.pending] : () => {
console.log("Pending");
},
[fetchAsyncPosts.fulfilled] : (state, {payload}) => {
console.log("Fulfilled");
return {...state, posts: payload};
},
[fetchAsyncPosts.rejected]: () => {
console.log("Rejected");
},
[fetchAsyncPostsDetail.fulfilled] : (state, {payload}) => {
console.log("Fulfilled");
return {...state, selectedPost: payload};
},
},
});
export const {addPosts, setSelectedSubreddit} = postSlice.actions;
export const selectSelectedSubreddit = (state) => state.selectedSubreddit;
export const getAllPosts = (state) => state.posts.posts;
export const getSelectedPost = (state) => state.posts.selectedPost;
export default postSlice.reducer;
App.js
import "./App.scss";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import PageNotFound from "./components/PageNotFound/PageNotFound";
import Header from "./components/Header/Header";
import Home from "./components/Home/Home";
import PostDetails from "./components/PostDetails/PostDetails";
import Footer from "./components/Footer/Footer";
import 'bootstrap/dist/css/bootstrap.min.css';
function App() {
return (
<div className="App">
<Router>
<Header/>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/:sub/comments/:postID" element={<PostDetails />} />
<Route path="*" element={ <PageNotFound />} />
</Routes>
</Router>
</div>
);
}
export default App;
Home.js:
import React, {useEffect} from 'react'
import { useDispatch, useSelector } from 'react-redux';
import PostListing from '../PostListing/PostListing'
import { fetchAsyncPosts } from '../../features-redux/posts/postSlice';
function Home() {
const dispatch = useDispatch();
const subreddit = useSelector((state) => state.posts.selectedSubreddit);
useEffect(() => {
dispatch(fetchAsyncPosts(subreddit));
}, [dispatch, subreddit]);
return (
<div>
<div className="jumbotron jumbotron-fluid">
<div className="container text-center">
<h1 className="display-4">Welcome to Tasteful Reddit</h1>
<p className="lead">Toggle between subreddits above to view their recipes.</p>
</div>
</div>
<PostListing />
</div>
)
}
export default Home
postListing.js:
import React from 'react'
import { useSelector } from 'react-redux'
import { getAllPosts } from '../../features-redux/posts/postSlice'
import PostCard from '../PostCard/PostCard';
function PostListing() {
const posts = useSelector(getAllPosts);
const rendering = () => posts.map((post, key) => {
return <PostCard key={key} data={post.data} />;
});
console.log(posts);
return (
<div className="post-wrapper">
<div className="post-container">
{rendering()}
</div>
</div>
)
}
export default PostListing
postCard.js:
import React from 'react'
import parse from 'html-react-parser';
import {Link} from 'react-router-dom';
function PostCard(props) {
const {data} = props;
/* Function to change escaped HTML to string */
const htmlDecode = (input) => {
var doc = new DOMParser().parseFromString(input, "text/html");
return doc.documentElement.textContent;
}
/* Decode reddit JSON's youtube embed HTML */
const youtubeHtmlString = htmlDecode(data.media_embed.content);
/* This function runs through the reddit data to make sure that there is a
an image for the post. If so, shows image
and if its a reddit hosted video or youtube video it will render the video.
Gallery-style posts & all else shows empty div*/
const mediaRender = () => {
if (data.thumbnail !== 'self' && data.thumbnail !== 'default' && data.is_self !== true && data.is_gallery !== true && data.domain !== 'youtu.be' && data.domain !== 'v.redd.it') {
return <img src = {data.url} alt={data.title} className="card-img-top"/>;
} if ( data.is_video == true) {
return (
<div>
<video controls preload = "none">
<source src={data.media.reddit_video.fallback_url} type="video/mp4"/>
Your browser does not support the video tag.
</video>
</div>
)
} if (data.domain == 'youtu.be') {
return (
<div className="Container">
{parse(youtubeHtmlString)}
</div>
)
} else {
return <div></div>
}
}
/* If only text & no photos, render text info*/
const renderSelf = () => {
if(data.is_self == true) {
return (<p>{data.selftext}</p>)
} else {
return <p></p>
}
}
return (
<div className="card mb-3 mx-auto text-center" style={{width: "70%"}}>
<div className="row g-0">
<div className="col-md-5">
{mediaRender()}
</div>
<div className="col-md-7">
<div className="card-body">
<h5 className="card-title">{parse(data.title)}</h5>
<div className="card-text">{renderSelf()}</div>
<div className="card-text"><small className="text-muted">By {data.author}</small></div>
<Link to={`/${data.subreddit}/comments/${data.id}`}>
<button className="btn btn-primary">Go to post</button>
</Link>
</div>
</div>
</div>
</div>
)
}
export default PostCard
postDetails.js:
import React, { useEffect } from 'react'
import { useParams } from 'react-router-dom';
import {useDispatch, useSelector} from 'react-redux';
import { fetchAsyncPostsDetail, getSelectedPost } from '../../features-redux/posts/postSlice';
function PostDetails() {
let {sub, postID} = useParams();
const dispatch = useDispatch();
const data = useSelector(getSelectedPost);
console.log(postID)
useEffect(() => {
dispatch(fetchAsyncPostsDetail(sub, postID));
console.log(dispatch(fetchAsyncPostsDetail(sub, postID)))
}, [dispatch, postID, sub]);
console.log(data);
return (
<div>
PostDetails
</div>
)
}
export default PostDetails
Any help would be appreciated, because I'm lost!
Thanks!
I figured it out today, for those interested!
I finally got it! I figured I was doing something wrong with react router, and that's why I couldn't get it to work but I didn't want to stop using react router. I tried many different ways to fix it, including putting both arguments in an object, I tried changing it by passing what I needed with a pathname AND a state, but the state didn't work right. think that I was passing the state in an incorrect way somehow. I think I wrote it like state{ permalink: data.permalink} or something. I also tried changing it so it only took one parameter, but for some reason the react router Link only wanted to use the post IDs and would go to my page not found if I tried to use permalink. After researching other ways to pass data using React Router, I landed on using From to grab the data from the previous page the user was on and used useLocation to grab the state.
Here is a snippet of what I changed in Link for in PostCard.js. The data was passed in props from postListing.js, just for reference:
return (
<div className="card mb-3 mx-auto text-center" style={{width: "70%"}}>
<div className="row g-0">
<div className="col-md-5">
{mediaRender()}
</div>
<div className="col-md-7">
<div className="card-body">
<h5 className="card-title">{parse(data.title)}</h5>
<div className="card-text">{renderSelf()}</div>
<div className="card-text"><small className="text-muted">By {data.author}</small></div>
<Link to={`/post/${data.id}`}
state={{ from: data}}>
<button className="btn btn-primary">Go to post</button>
</Link>
</div>
</div>
</div>
</div>
)
}
I also stopped using the postId to try and make the API call, and instead only used it to make the dynamic link to the component. After that, I used From's state to grab the permalink(from previous reddit post data) to make the API call to get the comment information.
Here is a snippet of PostDetails.js where I made the changes:
function PostDetails() {
const location = useLocation();
const {from} = location.state;
const comments = useSelector(getSelectedPost);
const dispatch = useDispatch();
useEffect( () => {
dispatch(getPostComments(from.permalink));
}, [dispatch]);
I also found out I was trying to access the data incorrectly in my API call, as the data was structured differently than I originally thought.
Here is the changed thunk in PostSlice.js:
export const getPostComments = createAsyncThunk('posts/getPostComments', async (permalink) => {
const response = await fetch(`http://www.reddit.com${permalink}.json`);
const json = await response.json();
return json[1].data.children.map((comment) => comment.data)
});
There were multiple things wrong with my react app, but hopefully this helps someone else! :)
The second argument to createAsyncThunk is the payloadCreator.
It's called with two arguments, arg which is a single value, and the thunkAPI object.
// First, create the thunk
const fetchUserById = createAsyncThunk(
'users/fetchByIdStatus',
async (userId, thunkAPI) => {
const response = await userAPI.fetchById(userId)
return response.data
}
)
// Later, dispatch the thunk as needed in the app
dispatch(fetchUserById(123))
You are passing the thunkAPI argument as the postID value in the GET request.
export const fetchAsyncPostsDetail = createAsyncThunk(
'posts/fetchAsyncPostsDetail',
async (sub, postID) => {
const response = await redditApi.get(`${sub}/comments/${postID}.json`)
return response.data.data.children;
}
);
If you need to pass multiple values to your thunk then pack them into a single object.
export const fetchAsyncPostsDetail = createAsyncThunk(
'posts/fetchAsyncPostsDetail',
async ({ sub, postID }, thunkAPI) => {
const response = await redditApi.get(`${sub}/comments/${postID}.json`)
return response.data.data.children;
}
);
...
useEffect(() => {
dispatch(fetchAsyncPostsDetail({ sub, postID }));
}, [dispatch, postID, sub]);

Resources