Next JS 13 data send from client component to server side component but show Not found - deployment

JS 13 and inside my ReadMoreButton client component i push my article data using useRouter hook of NEXT.
Not i can not use useRouter hook inside NEXT.JS server component so here i fetch searchParams and fetch that data.
here problem is before rendering i am checking if searchParams are defined or not not if i check in development everything work fine it render data but in production mode it show page not found error even if data is correctly send.
when i run next build it give me following output Output
and i am running side in production mode using next start and it show page not found when i do /article?serchParamsData.
You can check my whole code here : https://github.com/ssiwach8888/Next.JS-News-App
i also deploy production build on Vercel but it also show same error.
I am using NEXT.JS 13 with typescript
# ReadMoreButton.tsx "First Control goes here."
"use client";
type Props = {
article: NewsData;
};
import { useRouter } from "next/navigation";
//For navigate to SSC
const ReadMoreButton = ({ article }: Props) => {
const router = useRouter();
const handleClick = () => {
const queryString = Object.entries(article)
.map(([key, value]) => `${key}=${value}`)
.join("&");
const url = `/article?${queryString}`;
router.push(url);
};
return (
<button
className="bg-orange-400 h-10 rounded-b-lg dark:text-gray-900 hover:bg-orange-500"
onClick={handleClick}
>
Read More
</button>
);
};
export default ReadMoreButton;
# Article.tsx "Then we navigate to this page."
type Props = {
searchParams?: NewsData;
};
import { notFound } from "next/navigation";
import LiveTimestamp from "../Components/LiveTimestamp";
import Link from "next/link";
const ArticlePage = ({ searchParams }: Props) => {
if (
(searchParams && Object.entries(searchParams).length === 0) ||
!searchParams
) {
return notFound();
}
const article: NewsData = searchParams;
return (
<article className="mt-6">
<section className="flex flex-col lg:flex-row pb-24 px-0 lg:px-10">
<img
src={article.image === "null" ? "/no-image.jpeg" : article.image}
alt={article.title}
className="h-50 max-w-md mx-auto md:max-w-lg lg:max-w-xl object-contain rounded-lg shadow-md"
/>
<div className="px-8">
<Link legacyBehavior href={article.url || ""}>
<a target="_blank">
<h1 className="headerTitle hover:underline cursor-pointer px-0 pb-2">
{article.title}
</h1>
</a>
</Link>
<div className="flex divide-x-2 space-x-4">
<h2 className="font-bold">
By: {article.author !== "null" ? article.author : "Unknown"}
</h2>
<h2 className="font-bold pl-4">Source: {article.source}</h2>
<p className="pl-4">
<LiveTimestamp
time={
article.published_at === "null" ? "" : article.published_at
}
/>
</p>
</div>
<p className="pt-4 text-lg">{article.description}</p>
</div>
</section>
</article>
);
};
export default ArticlePage;

You just need to put the article page in [bracket] to make it dynamic so next js can fetch all pages otherwise it would display blank----
change article folder to [article]
more reference https://nextjs.org/docs/routing/dynamic-routes

Related

How to upload a single image file with next.js to mongodb?

When I'm uploading form data to mongodb, in the image section it shows this:
"C:\fakepath\imageName.jpg" with no actual image in it. And when I fetch the data from the database and map them, all the other data like title and body gets shown, but not the image. Because there wasn't any image to begin with. It was just a fake path.
So, how can I upload image file not the path to MongoDB.
I'm using Next.js and the mongodb npm package.
This is the pages/api/new-post.js file:
import { MongoClient } from "mongodb";
export default async function handler(req, res) {
if (req.method === 'POST') {
const data = req.body
const client = await MongoClient.connect('mongodb://localhost:27017/blog-nextjs')
const db = client.db()
const postCollections = db.collection('posts')
const result = await postCollections.insertOne(data)
console.log(result)
client.close()
res.status(201).json({message: 'Post Inserted'})
}
}
The form code I used in pages/new-post.js are:
import { useRef } from "react";
export default function NewPostForm(props) {
const titleInputRef = useRef()
const imageInputRef = useRef()
const bodyInputRef = useRef()
function submitHandler(e) {
e.preventDefault()
const enteredTitle = titleInputRef.current.value
const enteredImage = imageInputRef.current.value
const enteredBody = bodyInputRef.current.value
const postData = {
title: enteredTitle,
image: enteredImage,
body: enteredBody
}
props.onAddPost(postData)
}
return (
<div>
<form onSubmit={submitHandler}>
<div>
<label htmlFor="title">Title</label>
<input
placeholder="Post Title"
required
type="text"
ref={titleInputRef}
/>
</div>
<div>
<label htmlFor="body">Post</label>
<textarea
placeholder="Post Body "
required
ref={bodyInputRef}
></textarea>
</div>
<div>
<label htmlFor="image">Image</label>
<input
type="file"
required
placeholder="Image"
accept="image/png, image/gif, image/jpeg"
// accept="image/*"
ref={imageInputRef}
/>
</div>
<div><button>Post</button></div>
</form>
</div>
);
}
It's a bad approach to load images directly in MongoDb
You should store it to 3d party hostings and save only link(s) to your image.
Check related question

Data of radio button not being saved in Postgres DB even after a success message

Hi so I have these radio buttons where I want to save their data as json in my Postgres db . It is not being sent I get a message.success back that says I did but when i check my db nothing happens.
I don't exactly know where I am wrong so if u can help please do share.
PS: Im using Ant Design vue that's where the a- come from .
I do click on a button and it opens a modal where I have the radio buttons :
<template #modalite="{ record }">
<span>
<a-button
#click="showModalite(record)"
class="btn btn-sm btn-light mr-2"
>
<i class="fe fe-edit mr-2" />
Modalité
</a-button>
</span>
</template>
and here is my buttons code :
<a-modal
v-model:visible="visible"
:width="500"
#ok="ChangeModalite(modelInfo)"
>
<div class="row">
<a-radio-group name="radioGroup" v-model:value="traitement">
<div class="col-md-6">Négociation directe</div>
<div class="col-md-3">
<a-radio value="Négociation directe" v-model:checked="modalite.negociation" />
</div>
<div class="col-md-6">Appel à concurrence</div>
<div class="col-md-3">
<a-radio value="Appel à concurrence" v-model:checked="modalite.concurrence"/>
</div>
</a-radio-group>
</div>
</a-modal>
The script :
setup() {
const visible = ref(false)
const traitement = ref('Négociation directe');
const modalite = ref({
negociation:false,
concurrence:false,
})
const showModalite = (record) => {
modelInfo.value = record
modalite.value = { ...modalite.value, ...record.modalite }
visible.value = true
}
const ChangeModalite = (record) => {
console.log(record.id+": "+traitement.value)
axios.patch('/prop/' + record.id,{
modalite:modalite.value,
})
.then(()=>{
record.modalite=modalite.value
Object.assign(
dataSource.value.filter((item) => record.id === item.id),
record,
)
message.success(`successfully updated !!`)
visible.value = false
})
.catch((e)=>{
message.warning("smthg wrong ")
})
}
return {
dataSource,
modelInfo,
showModalite,
ChangeModalite,
modalite,
traitement,
}
},
}
So what happens now is i get the 'succefully updated ' msg without being really updated.where did i miss something?
I changed the type from json to string in my db everything works fine when I changed this line :axios.patch('/prop/' + record.id,{ modalite:modalite.value, }) to this axios.patch('/prop/' + record.id,{ modalite:traitement.value, })
so yeah data gets updated, still don't know why with the json type it's not working but at least i found a way if u have an explanation or suggestion it will be appriciated .

Adding a wp: featured image to loop when using a headless CMS via the Wordpress API and Vue.js

Would like to know how to implement the Wordpress Featured Image to multiple vue.js/nuxt.js based headless-CMS approaches using the Wordpress restful API.
Initially, I followed this immensely helpful tutorial headless-cms with nuxt and created a headless CMS via the wordpress api, and of course applied it to my use-case (here is a link to a live version nuxt-headless-cms-webapp. Unfortunately, I have been unable to figure out how to include a post's featured image as it is not covered in this particular tutorial. I then did a bit of research and ended up piecing together another project (vue.js), in which I was able to implement featured images. That being said I would like guidance with regard to implementing my working code in terms of the wp-featured image, to the original tutorial's project (as nuxt provides better routing and SEO options from my understanding. Thank you in advanced for any help!
First, here is the axios http request syntax found in the original tutorial (nuxt) project's index.js:
const siteURL = "https://indvillage.com"
export const state = () => ({
posts: [],
tags: []
})
export const mutations = {
updatePosts: (state, posts) => {
state.posts = posts
},
updateTags: (state, tags) => {
state.tags = tags
}
}
export const actions = {
async getPosts({ state, commit, dispatch }) {
if (state.posts.length) return
try {
let posts = await fetch(
`${siteURL}/wp-json/wp/v2/posts?_embed`
).then(res => res.json())
posts = posts
.filter(el => el.status === "publish")
.map(({ id, slug, title, excerpt, date, tags, content }) => ({
id,
slug,
title,
excerpt,
date,
tags,
content
}))
commit("updatePosts", posts)
} catch (err) {
console.log(err)
}
},
async getMedia({ state, commit }) {
if (state.media.length) return
try {
let media= await fetch(
`${siteURL}/wp-json/wp/v2/media?_embed`
).then(res => res.json())
commit("updatePosts", media)
} catch (err) {
console.log(err)
}
},
async getTags({ state, commit }) {
if (state.tags.length) return
let allTags = state.posts.reduce((acc, item) => {
return acc.concat(item.tags)
}, [])
allTags = allTags.join()
try {
let tags = await fetch(
`${siteURL}/wp-json/wp/v2/tags?page=1&per_page=40&include=${allTags}`
).then(res => res.json())
tags = tags.map(({ id, name }) => ({
id,
name
}))
commit("updateTags", tags)
} catch (err) {
console.log(err)
}
}
}
Next, we have the index.vue page where the above logic is implemented.
template>
<div>
<app-masthead></app-masthead>
<div class="posts">
<main>
<div class="post" v-for="post in sortedPosts" :key="post.id">
<h3>
<a :href="`blog/${post.slug}`">{{ post.title.rendered }}</a>
</h3>
<small>{{ post.date | dateformat }}</small>
<div v-html="post.excerpt.rendered"></div>
<a :href="`blog/${post.slug}`" class="readmore slide">Read more ⟶</a>
</div>
</main>
<!--<aside>
<h2 class="tags-title">Tags</h2>
<div class="tags-list">
<ul>
<li
#click="updateTag(tag)"
v-for="tag in tags"
:key="tag.id"
:class="[tag.id === selectedTag ? activeClass : '']"
>
<a>{{ tag.name }}</a>
<span v-if="tag.id === selectedTag">✕</span>
</li>
</ul>
</div>
</aside>-->
</div>
</div>
</template>
<script>
import AppMasthead from "#/components/AppMasthead.vue";
export default {
components: {
AppMasthead
},
data() {
return {
selectedTag: null,
activeClass: "active"
};
},
computed: {
posts() {
return this.$store.state.posts;
_embed = true;
},
tags() {
return this.$store.state.tags;
},
sortedPosts() {
if (!this.selectedTag) return this.posts;
return this.posts.filter(el => el.tags.includes(this.selectedTag));
}
},
created() {
this.$store.dispatch("getPosts");
},
methods: {
updateTag(tag) {
if (!this.selectedTag) {
this.selectedTag = tag.id;
} else {
this.selectedTag = null;
}
}
}
};
Here is a link to my project with working wordpress featured images! https://indvillage.netlify.app/
And here is the logic associated with the axious http request I used.
The question is how, do I include my logic in terms of the wp featured image to the initial nuxt tutorial without breaking things:
export default {
data() {
return {
postsUrl: "https://indvillage.com/wp-json/wp/v2/posts",
queryOptions: {
per_page: 6,
page: 1,
_embed: true
},`
posts: []
};
},
methods: {
// Get recent posts from wp
getRecentMessages() {
axios
.get(this.postsUrl, { params: this.queryOptions })
.then(response => {
this.posts = response.data;
console.log("Posts retrieved!");
})
//document.getElementById("test").id = "testing";
.catch(error => {
console.log(error);
});
},
getPostDate(date) {
return moment(date).format("111");
},
},
mounted() {
this.getRecentMessages();
}
}
Next, here is the App.vue template that displays the parsed information:
<template id="app">
<body>
<div class="row container">
<!-- looping through and displaying the array bound posts in HTML -->
<div class="col s4 m4" v-for="(post, index) in posts" :key="index" :id="'post'+index">
<div class="card" id="test">
<div class="card-image">
<!-- rendering the post's wp:featuredmedia in the image portion of the html/css card -->
<img
v-if="post._embedded['wp:featuredmedia']"
:src="post._embedded['wp:featuredmedia'][0].source_url"
/>
</div>
<!-- rendering the post.excerpt to the html/css card container -->
<div class="card-content" v-html="post.excerpt.rendered"></div>
<div class="card-action">
<!-- rendering the post title to the action portion of the html/css card -->
{{ post.title.rendered }}
</div>
</div>
</div>
</body>
</template>
Please let me know if anyone has any suggestions with regard to implementing wp:featuredmedia to the code derived from the first project/tutorial (nuxt.js)
Thanks again! Feel free to email with further questions

react-google-maps StandaloneSearchBox set specific country restriction?

I am trying to set a specific country restriction using react-google-maps StandaloneSearchBox.
I have tried componentRestrictions, but I'm not sure how to use it.
Sharing my code below:
export const AutoCompleteSearchBox = compose(
withProps({
googleMapURL:googleMapUrl,
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px`, top:'3px' }} />,
}),
lifecycle({
componentWillMount() {
const refs = {}
this.setState({
types: ['(regions)'],
componentRestrictions: {country: "bd"},
onSearchBoxMounted:ref =>{ refs.searchBox = ref; },
onPlacesChanged:()=>{
const places = refs.searchBox.getPlaces();
this.props.onPlacesChanged(places);
},
})
const options = {
types: ['(regions)'],
componentRestrictions:{ country: 'bd' }
}
},
}),
withScriptjs
)`(props =>
<div data-standalone-searchbox="">
<StandaloneSearchBox
ref={props.onSearchBoxMounted}
bounds={props.bounds}
onPlacesChanged={props.onPlacesChanged}
controlPosition={ window.google.maps.ControlPosition.TOP_LEFT}
>
<TextField
className={props.inputClass}
placeholder={props.inputPlaceholder}
label={props.inputLabel}
name={props.inputName}
value={props.inputValue}
onChange={props.inputOnChange}
helperText={props.inputHelperText}
error={props.inputError}
/>
</StandaloneSearchBox>
</div>
);`
How can I solve this problem?
You can't add such restrictions for the SearchBox results, but you can specify the area towards which to bias query predictions. Predictions are biased towards, but not restricted to, queries targeting these bounds.
If you want to show only specific places, then you can Google Place Autocomplete feature. For it you don't event need to use additional React libraries for Google Maps. Here's the example:
import React, { Component } from 'react';
import Script from 'react-load-script'
class LocationMap extends Component {
handleScriptLoad() {
const inputEl = document.getElementById('address-input');
/*global google*/
var options = {
//types: ['address'],
componentRestrictions: {country: 'by'}
};
this.autocomplete = new google.maps.places.Autocomplete(inputEl, options);
this.autocomplete.addListener('place_changed', this.handlePlaceSelect.bind(this));
}
handlePlaceSelect() {
console.log(this.autocomplete.getPlace());
}
render() {
return (
<section>
<Script
url="https://maps.googleapis.com/maps/api/js?key=API_KEY&v=3.33&libraries=places&language=en&region=US"
onLoad={this.handleScriptLoad.bind(this)}
/>
<div className="form-group">
<label htmlFor="address-map">Enter address</label>
<input type="text"
autoComplete="new-password"
className="form-control"
id="address-input"
name="address"/>
</div>
</section>
);
}
}
export default LocationMap;
Don't forget to add react-load-script package: npm i react-load-script --save

Im getting some weird errors with MaterialUI Stepper "Cannot read property stepIndex of undefined"

I'm using MaterialUI and I'm getting the error -
"Uncaught TypeError: Cannot read property 'stepIndex' of undefined"
In my Chrome console
I haven't had this error with any of the other Material-UI React Components. I am pretty new to React so if this is a stupid mistake please bear with me.
I cant seem to solve the problem.
I'm using React 5.3.1.
My code:
class HorizontalLinearStepper extends React.Component {
handleNext() {
const {stepIndex} = this.state;
this.setState({stepIndex: stepIndex + 1,finished: stepIndex >= 2});
};
handlePrev() {
const {stepIndex} = this.state;
if (stepIndex > 0) {
this.setState({
stepIndex: stepIndex - 1
});
}
};
getStepContent(stepIndex) {
switch (stepIndex) {
case 0:
return 'Select campaign settings...';
case 1:
return 'What is an ad group anyways?';
default:
return 'You\'re a long way from home sonny jim!';
}
}
render() {
const {finished, stepIndex} = this.state;
return (
<div>
<Stepper activeStep={stepIndex}>
<Step>
<StepLabel>Select campaign settings</StepLabel>
</Step>
<Step>
<StepLabel>Create an ad group</StepLabel>
</Step>
</Stepper>
<div style={contentStyle}>
{finished ? (
<p>
<a
href="#"
onClick={(event) => {
event.preventDefault();
this.setState({stepIndex: 0, finished: false});
}}
>
Click here
</a> to reset the example.
</p>
) : (
<div>
<p>{this.getStepContent(stepIndex)}</p>
<div style={{marginTop: 12}}>
<FlatButton
label="Back"
disabled={stepIndex === 0}
onTouchTap={this.handlePrev}
style={{marginRight: 12}}
/>
<RaisedButton
label={stepIndex === 2 ? 'Finish' : 'Next'}
primary={true}
onTouchTap={this.handleNext}
/>
</div>
</div>
)}
</div>
</div>
);
}
}
export default HorizontalLinearStepper;
Thanks!
<FlatButton
label="Back"
disabled={stepIndex === 0}
onTouchTap={this.handlePrev.bind(this)}
style={{marginRight: 12}}
/>
<RaisedButton
label={stepIndex === 2 ? 'Finish' : 'Next'}
primary={true}
onTouchTap={this.handleNext.bind(this)}
/>
You need to bind the handlers as they will be run in a different context and will loose the right meaning of this, so we bind the handlers to keep the right context of this.