MERN blog - how to display posts latest first? - node.js

I want to be able to display the newest blog posts first, at the moment when a user adds a post the latest post adds below the previous one - I want the opposite to happen so the newest post is the first post.
import Header from "../../components/header/Header";
import Posts from "../../components/posts/Posts";
import Sidebar from "../../components/sidebar/Sidebar";
import "./home.css";
import axios from "axios";
import { useLocation } from "react-router";
export default function Home() {
const [posts, setPosts] = useState([]);
const { search } = useLocation();
useEffect(() => {
const fetchPosts = async () => {
const res = await axios.get("/posts" + search);
setPosts(res.data);
};
fetchPosts();
}, [search]);
return (
<>
<Header />
<div className="home">
<Posts posts={posts} />
<Sidebar />
</div>
</>
);
}
Thank you!

Ideally sorted data should be served from API response. Your API call would look something like this - /posted?orderBy=createdAt.
If you want to achieve this from client side, you may use array reverse()
method like this - setPosts(res.data.reverse());

Related

How to map dynamic routes to components outside pages folder in a NextJs multi tenant application

I am following this template here to create a Multi-tenant application using NextJS.
However, I am stucked at how to properly resolve the routing of the pages.
My pages folder is structured in this manner
pages/
_sites/[site]
[path.jsx]
index.jsx
I have the routing logic inside[path.jsx] file above
I have moved all my components from the pages folder to another folder called components.
Now, when a user visits for example james.mydomain.com/blog I wish to load the blog component from the components folder.
How can that be neatly done without too much hardcoding?
Here is what I have attempted but the page only freezes without loading the component:
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import Loading from "react-loading";
export default function SiteComponent(props) {
const router = useRouter();
const [component, setComponent] = useState(null);
const { path } = router.query;
const loadComponent = async (path) => {
const importedComponent = await import(`../../../src/components/${path}`);
setComponent(importedComponent.default);
}
useEffect(() => {
if (path) {
loadComponent(path);
}
}, []);
return (
component ? <component /> : <Loading color="teal" type="bubble" />
);
}
Is there a way to do this neatly without the above dynamic component loading?
I feel the above code may not even work properly on the occasion I wish to load a nested route eg. james.mydomain.com/blog/categories.
Please kindly suggest a cleaner approach.

Pulling Data From Node.js Rest Api Into React with axios

I am New to react, Node.js so I apologize if this is simple. I have been trying to pull Data From A Node.js Api Running Express into a React Component with Axios. I have tried many different ways and have searched for a solution with no luck. I am unable to access the Id as well as the ProductName
JSON DATA
{"Results":
[
{"id":4,"productName":"Flap Disc"}, {"id":5,"productName":"Fiber Disc"}
]
}
For whatever reason I am unable to Access the data inside these Objects.
CODE
export default function Parent () {
const [products, setProducts] = React.useState('');
const url = 'http://localhost:3040/';
React.useEffect(()=>{
async function getProduct(){
const response = await axios.get(`${url}`);
const a = (response.data.Results)
setProducts(a.map((item)=>
{item}
))
}
getProduct()
}, [])
return(
<div>
{
console.log(products)
}
</div>
)
}
Logging out inside JSX won't do anything. What you want to do is map over the data and display it as a component. Change your return to something more like this
return (
<div>
{products?.map((product) => <p>{product.name}<p>)
</div>
)
You should also change the default value fo products from an empty string to an empty array
const [products, setProducts] = React.useState([])

Unable to send api response data from express to react after refreshing the page

I'm learning react and node js with express framework and I'm working on a project where I need to retrieve API data from express to react.
I retrieved data from backend express js where I made a simple json value. My backend server.js code is given below.
server.js
const express = require('express')
const app = express()
const PORT = 3001;
app .get('/api/contents',(req,res)=>{
const contents=[
{
"id":0,
"heading":"Joshua Tree Overnight Adventure",
"content":"A sight in the blue sea..."
},
{
"id":1,
"heading":"Catch waves with an adventure guide",
"content":"Lorem.."
},
{
"id":2,
"heading":"Catch waves with an adventure guide",
"content":"Lorem epsum ..."
}
];
res.json(contents)
})
app.listen(PORT,()=>{
console.log("express server is running...")
})
In react app, I used axios to retrieve those values from backend and tried to pass the api values of content with id= 0 as props in "TheLatestArticles" component. I have updated proxy in package.json in react to connect backend. The below code is the mainhomepage component where it is enclosed with TheLatestArticles component with props value
MainHomePage.js
import axios from 'axios';
import {useState,useEffect} from 'react'
function MainHomePage(){
const [content,setContent]=useState([]);
useEffect(()=>{
const fetchPosts = async ()=>{
const res =await axios.get("/api/contents")
setContent(res.data)
console.log(res)
}
fetchPosts()
},[])
return (
<>
<TheLatestArticle content={content} />
</>
);
}
export default MainHomePage;
TheLatestArticle.js
import cardImage from "./../../Images/card.jpg"
import './TheLatestArticleCard.css';
const TheLatestArticleCard=(props)=>{
console.log(props)
return(
<>
<div className="card">
<div className="image">
<img src={cardImage} alt="cardimg"/>
</div>
<div className="content">
<p className="heading">{props.content.heading}</p>
<p className="body-content">{props.content.content}</p>
<div className="details">
<p className="details-info">Travel <span className="details-info-2">/ August 21 2017</span></p>
</div>
</div>
</div>
</>
)
}
export default TheLatestArticleCard;
When I run the application, It displayed all the api values in the screen given below.
I console.log the api values inside useEffect and it displayed all the api values perfectly.
But when I refresh the page, the api value became undefined and gave me this error
Can you please solve me this issue with the reason behind this error? Thanks a lot!
Try it like this
{(content && content.length > 0) && <TheLatestArticle content={content} />}
Since your API call is async there won't be any data in content initially. After a while, your API is called and data is fetched. Then you will have data. To prevent TheLatestArticle to blow up we add some conditions when to show that component. The error in the screenshot is when you try to use a property heading from content where content is empty.
Now with the condition, TheLatestArticle will not render until there is some data.
Update
You are using <TheLatestArticle content={content} /> and content is assumed to be an object. But as per your code, it's an array. If you are not already using content.map((c)=> <TheLatestArticle content={c} />) you should do that.

How to get file from input tag in react client side app

I am creating a react app that downloads youtube videos when given their URL. I am using this npm package to help download the files. I keep on getting the error:
TypeError: fs__WEBPACK_IMPORTED_MODULE_3___default.a.createWriteStream is not a function
I think the problem is that client-side requires that the user uploads a file and I'm not super sure how to do that. I know that I can use an input tag like:
<input
type="file"
id="fileInput"
name="UserFile"
onChange={this.handleClick(this.files)}
/>
Then, In my HandleClick method, I have to use ytdl(url).pipe("file inputted by user");
however, I do not know how to get the user's file from the input tag. I have left my recent code below. Please let me know if you guys need anymore information or if I was not clear about anything. Thank you!
import React from "react";
import "../../css/Widget.css";
import ytdl from "ytdl-core";
import fs from "fs";
// https://github.com/fent/node-ytdl-core
// npm install ytdl-core#latest
//const fs = require("fs");
//const ytdl = require("ytdl-core");
class VideoDownload extends React.Component {
constructor(props) {
super(props);
this.state = {
videoURL: "",
};
}
handleClick = (idk) => {
var input = this.refs.myInput;
//var url = input.value;
var url = "https://www.youtube.com/watch?v=OISEEL5eBqg";
//console.log(url);
let userInput = document.getElementById("fileInput");
//console.log("userInput: ", userInput);
console.log("idk: ", idk);
//ytdl(url).pipe(fs.createWriteStream("trial.flv"));
/*
need this:
ytdl(url).pipe("file that the user inputted")
*/
};
render() {
return (
<div className="VD-Main">
<h1>Video Downloader</h1>
<input
type="file"
id="fileInput"
name="myfile"
onChange={this.handleClick(this.files)}
/>
<input type="text" ref="myInput" placeholder="Enter Youtube URL" />
<input
className="inputButton"
type="button"
value="Enter Link"
onClick={this.handleClick}
/>
</div>
);
}
}
export default VideoDownload;
That's how you can do it
handleClick(event) {
const reader = new FileReader();
reader.onloadend = () => {
//handle 'reader.result' as you like
}
reader.readAsDataUrl(event.target.files[0]);
}

Import contentful in to react-native

I am extremely excited about using contentful for my project, but I can't get the JS library to work in a react-native project.
I get the following error:
I have tried the following approaches:
import contentful from 'contentful';
// or
var contentful = require('contentful');
You can reproduce the bug by going to this repo and following the steps I have provided.
Help would be greatly appreciated.
I am maintaining the Contentful sdk. I've put together a simple example
that shows how to use the SDK in React Native, you can check it here
It is basically getting a list of items from one of our example spaces and display the names in a ListView.Check indes.ios.js.
It looks like there is something wrong with the caching in your machine or so.
Anyway I hope this helps.If you have more problems please feel free to create issues in our github page
[UPDATE]
you can now configure the axios instance used in the SDK to use a different adapter. You can pass that when calling createClient
adapter: config => {
config.adapter = null // this is important if it is passing to another axios instance
// an http client combatible with React Native
return fetch(config)
}
Best,
Khaled
I've tried every option and it will never work using the Contentful SDK.
However, you can get it with REST and transform the response using the types from the contentful lib.
import axios from 'axios';
import {EntryCollection} from 'contentful';
import Env from '../Env';
const contentfulApi = 'https://cdn.contentful.com';
/**
* Default locale used in contentful calls
*
* #see {#link getContentfulEntries}
* #constant
*/
export const ContentfulLocale = 'sv';
/**
* #typedef ContentfulProps
* #param locale optional locale to use. Default is {#link ContentfulLocale}
* #param entryType content type in contentful model
*/
type ContentfulProps = {
entryType: string;
locale?: string;
};
/**
* Get entries from Contentful content API
* #param props See {#link ContentfulProps}
*/
export const getContentfulEntries = async <T>(
props: ContentfulProps,
): Promise<EntryCollection<T>> => {
const client = axios.create({
baseURL: `${contentfulApi}/spaces/${Env.CONTENTFUL_SPACEID}/environments/master/entries?`,
timeout: 1000,
headers: {Authorization: `Bearer ${Env.CONTENTFUL_TOKEN}`},
});
const result = await client.get<EntryCollection<T>>(
'&content_type=' + props.entryType,
);
return result.data;
};
export default getContentfulEntries;
I think the best way to use Contentful APIs with React Native is to use Apollo client and graphQL packages.
I worked around the same and get it done.
Install Apollo client and GraphQL npm package
npm install #apollo/client graphql
Install react-native async storage to store cache
npm install #react-native-async-storage/async-storage
Install apollo cache persist to persist the cache
npm install apollo3-cache-persist
you can read apollographql official documents for implementation
Create ApolloClient in the app.tsx/.js file
import { ApolloClient, ApolloProvider, InMemoryCache } from '#apollo/client';
const cache = new InMemoryCache();
const client = new ApolloClient({
uri: 'https://graphql.contentful.com/content/v1/spaces/{SPACE_ID}',
cache,
credentials: 'same-origin',
headers: {
Authorization: `Bearer {CDA-Access-Token}`,
},
});
Wrap all components in ApolloProvider
const App = () => {
const [loadingCache, setLoadingCache] = useState(true);
useEffect(() => {
persistCache({
cache,
storage: AsyncStorage,
}).then(() => setLoadingCache(false));
}, []);
if (loadingCache) {
return <Loader />;
}
return (
<ApolloProvider client={client}>
<SafeAreaView style={{flex: 1}}>
<Posts />
</SafeAreaView>
</ApolloProvider>
);
};
export default App;
Import gql and useQuery to fetch data
import { gql, useQuery } from '#apollo/client';
Now, write GraphQL query
const QUERY_COLLECTION = gql`
{
postsCollection {
items {
title
author
publishDate
inshorts
featuredImage {
url
}
}
}
}
`;
Fetch data using useQuery function
const { data, loading } = useQuery(QUERY_COLLECTION);
That's all to fetch data from Contentful in React Native App.
To read this in detailed, have a look to this post

Resources