Inserting JSON Payloads into MongoDB Atlas with NextJS - javascript

I am trying to insert some data into MongoDB Atlas. The execution is going through, but it only comes into the database with an "undefined" data field. I'm guessing that I am not passing the data to it correctly. I am wanting the json payload to get inserted into a MongoDB database automatically when the payload has been received.
Here is the code on my Nextjs index.js page that I am working with:
import Image from 'next/image'
import classes from "./GeneratePage.module.css";
import Head from "next/head";
import { useState } from "react";
import React from 'react';
import Link from 'next/link'
import {signIn, signOut, useSession} from 'next-auth/react'
//import { saveAs } from "file-saver";
import SVG from '/pages/gallery/images/download.svg'
export default function Generate() {
const { data: session, status} = useSession();
const [token, setToken] = useState("sess-xxxxxxxxxxxxxxxxxxxxxxxxxx");
const [query, setQuery] = useState("");
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const loadIt = async (inSert) => {
const newData = await fetch(`http://localhost:3000/api/storeDalle?Upload=${inSert}`);
const res = await newData.json();
console.log(res);}
function GetDalle2() {
if (token != "" && query != "") {
setError(false);
setLoading(true);
fetch(`/api/dalle2?k=${token}&q=${query}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
})
.then((res) => res.json())
.then((data) => {
setResults(data.result);
setLoading(false);
loadIt(JSON.stringify(data).toArray);
})
.catch((err) => {
console.log(err);
setLoading(false);
setError(true);
});
} else {
setError(true);
}
}
return (
<div className={classes.container}>
<Head>
<title>Atlas Tattoo Development</title>
</Head>
<main className={classes.main}>
{!session && (
<>
<br />
<button className={classes.btn_neu} onClick={signIn}>Sign In</button>
</>
)}
{
session && (
<>
<h1 className={classes.title}><span className={classes.titleColor}>Get Inked With The Future</span></h1>
<p className={classes.description}>
<input
id="query"
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Query"
/>
</p>{" "}
<button className={classes.btn_neu} onClick={GetDalle2}>
Generate</button>
{error ? (
<div className={classes.error}>Something went wrong..Try again</div>
) : (
<></>
)}
{loading &&
<div className="wrapper">
<br />
<br />
<div className="circle"></div>
<div className="circle"></div>
<div className="circle"></div>
<div className="shadow"></div>
<div className="shadow"></div>
<div className="shadow"></div>
</div>}
<div className={classes.grid}>
{results.map((result) => {
return (
<div key={result.generation.image_path.toString()} className={classes.card}>
<Image key={result.generation.image_path.toString()} className={classes.imgPreview} src={result.generation.image_path} alt=' ' width='300vw' height='300vw'/>
<div>
<button className={classes.btn_neu_download}>
<SVG className={classes.download_image}/>
</button>
</div>
</div>
);
})}
</div>
</>
)
}
</main>
</div>
);
}
Here is the code for the mongodb function that the fetch process goes to:
import clientPromise from "../../lib/mongodb";
export default async (req, res) => {
try {
const client = await clientPromise;
const db = client.db("sample_mflix");
const newData = req.query;
const result = await db
.collection("movies")
.insertOne(newData);
console.log(`A document was inserted with the _id: ${result.insertedId}`)
res.json(result);}
catch (e) {
console.error(e);
}
};
Note: I can retrieve the data and display it on the screen via the map function found on the index page in the first code snippet:
<div className={classes.grid}>
{results.map((result) => {
return (
<div key={result.generation.image_path.toString()} className={classes.card}>
<Image key={result.generation.image_path.toString()} className={classes.imgPreview} src={result.generation.image_path} alt=' ' width='300vw' height='300vw'/>
<div>
<button className={classes.btn_neu_download}>
<SVG className={classes.download_image}/>
</button>
</div>
</div>
);
})}

Related

How to display Pokemon image in react js?

I am new in react JS technology , and I got a assignment from my job to display Pokemon name and image , I displayed name but I am Failed with displaying image of Pokemon, Can anyone help me to display image of pokemon. I f you have any query regarding my question please free feel to ask me.
import React, { useEffect, useState } from "react";
import Axios from "axios";
const Pokemonapi = () => {
const [text, setText] = useState("");
const [data, setData] = useState([]);
const Search = () => {
if (text == "") {
alert("Please Enter a name to be search");
} else {
searchPokemon();
setText("");
}
};
const searchPokemon = async () => {
const response = await Axios.get(
`https://pokeapi.co/api/v2/pokemon/${text}`
);
// const getdata = await response.json();
setData(response.data.results);
console.log(response);
};
useEffect(() => {
searchPokemon();
}, []);
return (
<div>
<div className="container-fluid jumbotron">
<div className="input-group mb-3">
<input
type="text"
className="form-control shadow-none"
placeholder="Search Pokemon"
value={text}
onChange={(e) => setText(e.target.value)}
/>
<div className="input-group-append">
<span
className="input-group-text"
id="basic-addon2"
onClick={Search}
>
Search
</span>
</div>
</div>
</div>
{data.map((dat, index) => {
return (
<div key={index}>
<h2>{dat.name}</h2>
<img src={dat.sprites.other.dream_world.front_default} />
</div>
);
})}
</div>
);
};
export default Pokemonapi;
It depends on what that api is returning , if it returns the url of the image , you can use
<img src={dat.sprites.other.dream_world.front_default} />, assuming that
front_default=url but if it returns a base64 encode of the image , then you need to use
<img src=`data:image/png;base64,${dat.sprites.other.dream_world.front_default}` />

Update a React Element with the Data of Another Component's API Response

I am trying to make a simple react app that pulls info from a MySQL database ("username", "balance", "purchases").
So far, I've used node and react to pull from the database with an HTTP query and to display each element on the website.
I then created the API query for searching the database for all entries that start with what I've typed into the search bar.
The issue I'm running into is how do I change the state of the elements that display the username, etc with the new filtered information from the API query? The search bar and data elements are two separate components so I can't use the use effect hook natively.
I cant use the filter method because the database is huge and I've sent my query limit to 100.
Here's my code so far:
PlayerData.js
import axios from 'axios';
import React,{useState, useEffect} from 'react';
const Player = () => {
const [playerData,setPlayerData]=useState([])
useEffect(()=>{
axios.get("http://localhost:3001/api/get").then((res)=>{
console.log(res.data)
setPlayerData(res.data)
})
.catch(err=>{
console.log(err);
})
},[])
return (
<>
{playerData.map((data,id)=>{
return <div className="Player" key={id}>
<span className="Username"> { data.name } </span>
<span className="Crystals"> { data.balance } </span>
<span className="DateModi"> {Object.keys(JSON.parse(data.items)).length} </span>
</div>
})}
</>
)
};
export default Player;
SearchBar.js
import { useState } from "react";
import axios from 'axios'
const Search = () => {
const [searchTerm, setSearchTerm] = useState("")
axios.get(`http://localhost:3001/api/getSearchName/${searchTerm}`).then((res)=>{
console.log(res.data)
})
return (
<div className="Search">
<input className = "InputField" type="text" placeholder="Enter Username:" onChange={e => {setSearchTerm(e.target.value)}}/>
<span className="SearchButton" onClick={console.log(searchTerm)}>
Search
</span>
</div>
)
};
export default Search;
If I understood the question correctly, you need to set the state of PlayerData to a shared component(App), and pass it to the Player.js component. Then when searching it will be overwritten and update the information in the Player.js
function App() {
const [playerData, setPlayerData] = useState([]);
useEffect(() => {
fetchData();
}, []);
const fetchData = () =>
axios
.get("http://localhost:3001/api/get")
.then((res) => {
setPlayerData(res.data);
})
.catch((err) => {
console.log(err);
});
const handleSearch = (text) => {
const clearText = text.trim();
if (!clearText.length) {
fetchData();
return;
}
axios
.get(`http://localhost:3001/api/getSearchName/${clearText}`)
.then((res) => {
setPlayerData(res.data);
});
};
return (
<div>
<div>
<Search handleSearch={handleSearch} />
</div>
<div>
<Player playerData={playerData} />
</div>
</div>
);
}
Search.js
const Search = ({ handleSearch }) => {
const [searchTerm, setSearchTerm] = useState("");
return (
<div className="Search">
<input
className="InputField"
type="text"
placeholder="Enter Username:"
onChange={(e) => {
setSearchTerm(e.target.value);
}}
/>
<span className="SearchButton" onClick={() => handleSearch(searchTerm)}>
Search
</span>
</div>
);
};
Player.js
const Player = ({ playerData }) => {
return (
<>
{playerData?.length ? (
playerData.map((data, id) => {
return (
<div className="Player" key={id}>
<span className="Username"> {data.name} </span>
<span className="Crystals"> {data.balance} </span>
<span className="DateModi">
{" "}
{Object.keys(JSON.parse(data.items)).length}{" "}
</span>
</div>
);
})
) : (
<div>Loading...</div>
)}
</>
);
};

How can I collapse an accordion from a child component in react

I am creating a page to update product details on an e-commerce site I am building using NextJS, and I have the image upload section nested inside an accordion on the individual item page. Once images have been uploaded, I would like to clear the upload form and close the accordion. It is closing the accordion I am having trouble with.
ImageUploadAccordion.js:
import React, {useRef} from 'react';
import {Accordion} from 'react-bootstrap'
import ImageUpload from './ImageUpload'
export default function ImageUploadAccordion({ item }) {
const accordionRef = useRef(null);
const toggleAccordion = () => {
accordionRef.current.click();
}
return (
<Accordion ref={accordionRef} defaultActiveKey="0">
<Accordion.Item eventKey="1">
<Accordion.Header>
<span className="btn btn-outline-success">Upload Images</span>
</Accordion.Header>
<Accordion.Body>
<ImageUpload
toggle={toggleAccordion}
item={item}
/>
</Accordion.Body>
</Accordion.Item>
</Accordion>
)
}
ImageUpload.js:
import React, {useState} from 'react';
import { useRouter } from 'next/router'
export default function ImageUpload({ item, toggle }) {
const router = useRouter()
const [images, setImages] = useState([])
const [imageURLS, setImageURLS] = useState([])
const [tags, setTags] = useState([])
const [theInputKey, setTheInputKey] = useState('')
const uploadImageToClient = (event) => {
if (event.target.files && event.target.files[0]) {
setImages((imageList) => [...imageList, {"index": images.length, "data": event.target.files[0]}]);
setImageURLS((urlList) => [
...urlList,
URL.createObjectURL(event.target.files[0])
]);
}
let randomString = Math.random().toString(36);
setTheInputKey(randomString)
};
const uploadTagToClient = (e) => {
if (event.target.value) {
const name = e.target.getAttribute("name")
// const i = event.target.value;
// document.getElementById("image-upload")
setTags((tagList) => [...tagList, {"name": name, "tag": e.target.value}]);
}
};
const removeImage = (name) => {
// debug
alert(`Trying to remove image index ${name}`)
let newImages = []
let newTags = []
setImages(images.filter(image => image.data.name !== name));
setTags(tags.filter(tag => tag.name !== name));
}
const uploadToServer = async (e) => {
const body = new FormData()
images.map((file, index) => {
body.append(`file${index}`, file.data);
});
// Use the filenames as keys then we can retrieve server side once we have the images
tags.map((tag, index) => {
body.append(tag.name, tag.tag)
})
const response = await fetch("/api/file", {
method: "POST",
"Content-Type": "multipart/form-data",
body
})
var message = await response.json();
alert(message['message'])
setImages([])
setTags([])
toggle()
};
const openImageUploadDialogue = () =>{
document.getElementById("image-upload").click()
}
return (
<div className="container">
<input style={{display:'none'}} accept="image/*" id="image-upload" type="file" key={theInputKey || '' } className="btn btn-outline-success-inverse" onChange={uploadImageToClient} />
<button className="btn btn-outline-success-inverse" onClick={openImageUploadDialogue} >
Add Image
</button>
<hr className = "text-pink"/>
<div className="row">
<div className="col d-flex flex-wrap">
{images.map((file, index) => {
return (
<div className="div p-1" key={file.data.name}>
<p className="text-pink">{file.data.name}</p>
<p>Tag</p>
<input type="text" name={file.data.name} id={`${file.data.name}`} onChange={uploadTagToClient} />
<img src={imageURLS[index]} height="200" width="150" />
<div className="btn btn-outline-success-inverse" onClick={ () =>removeImage(file.data.name)}>Remove Image</div>
</div>
);
})}
</div>
<button
className="btn btn-outline-success-inverse"
type="submit"
onClick={uploadToServer}
>
Upload Images
</button>
</div>
</div>
);
}
I tried by creating a reference to the accordion using useRef, and a function which uses this reference to activate the click event, which I passed to the ImageUpload component, according to another answer to a similar question, but it doesn't seem to work and I'm unsure as to why.
Any help always appreciated :-)
I believe you have the wrong target as the ref, update it to target the button that is automatically generated to wrap the header content.
<h2 class="accordion-header"><button type="button" aria-expanded="true" class="accordion-button"><span class="btn btn-outline-success">Upload Images</span></button></h2>
Rudimentary example:
export default function ImageUploadAccordion({ item }) {
const accordionRef = useRef(null);
const toggleAccordion = () => {
accordionRef.current.querySelector('button').click();
}
return (
<Accordion defaultActiveKey="0">
<Accordion.Item eventKey="1">
<Accordion.Header ref={accordionRef}>
<span className="btn btn-outline-success">Upload Images</span>
</Accordion.Header>
<Accordion.Body>
<ImageUpload
toggle={toggleAccordion}
item={item}
/>
</Accordion.Body>
</Accordion.Item>
</Accordion>
)
}

How to re-fetch data after doing a filter in React.js with useContext

I got this component in React.js which make different kinds of filtering when I click a button, this is my code:
import React, { useContext } from 'react';
import { ModelsContext } from "../context/ModelsContext";
const FilterNav = () => {
const { modelos, guardarModelo } = useContext(ModelsContext);
const filterSegment = e => {
const segment = modelos.filter(modelo => modelo.segment === e.target.name);
guardarModelo(segment);
}
return (
<nav className="filter-container">
<div className="container">
<h3 className="filter-element-title">Filtrar por</h3>
<button type="button" className="filter-element">Todos</button>
<button type="button" className="filter-element" name="Autos" onClick={filterSegment}>Autos</button>
<button type="button" className="filter-element" name="Pickups y Comerciales" onClick={filterSegment}>Pickups y Comerciales</button>
<button type="button" className="filter-element" name="SUVs y Crossovers" onClick={filterSegment}>SUVs y Crossovers</button>
</div>
<p className="filter-element-last">Ordenar por ^</p>
</nav>
);
}
export default FilterNav;
The information I get from the api with useContext in ModelsContext.jsx, here is what I wrote so far:
import React, { createContext, useState, useEffect } from 'react';
export const ModelsContext = createContext();
const ModelsProvider = (props) => {
//State de modelos
const [modelos, guardarModelo] = useState([]);
const consultarAPI = async () => {
const api = await fetch("https://challenge.agenciaego.tech/models");
const modelos = await api.json();
guardarModelo(modelos);
}
//Cargar un modelo
useEffect(() => {
consultarAPI()
}, []);
return (
<ModelsContext.Provider
value={{
modelos,
guardarModelo
}}
>
{props.children}
</ModelsContext.Provider>
)
}
export default ModelsProvider;
My issue is that when I filter the API modelos throught the filterSegment function I don't know how to re-fetch the data from the API, because when I do a new call to the filterSegment function it filters the filtered data. I've tried to add a boolean state, and I was thinking about adding another state with allthedata, but I really lost about implementing it, I'm still very new to React.js.
I've search through stack overflow and google and I cannot get the answer, If you can give me a clue or some sort of guidance it will be appreciated.
Thanks so much!
You can add another state in the ModelsContext:
//State de modelos
const [modelos, guardarModelo] = useState([]);
const [allModelos, guardarAllModelo] = useState([]);
const consultarAPI = async () => {
const api = await fetch("https://challenge.agenciaego.tech/models");
const modelos = await api.json();
guardarAllModelo(modelos);
//uncomment if you want to have initial value for modelos state
//guardarModelo(modelos);
}
// some codes ...
<ModelsContext.Provider
value={{
allModelos,
modelos,
guardarModelo
}}
>
{props.children}
</ModelsContext.Provider>
Then in the FilterNav component:
const {allModelos, modelos, guardarModelo } = useContext(ModelsContext);
const filterSegment = e => {
const segment = allModelos.filter(modelo => modelo.segment === e.target.name);
guardarModelo(segment);
}
But this does not really re-fetch data from your web api. It just re-filters the first fetched data. if you want to re-fetch data from web api you can add consultarAPI in your context provider then call it somewhere.
Thanks code is working
This is my Portfolio gallery code First time load all data when click category then get category dataenter code here
Thanks code is working
This is my Portfolio gallery code First time load all data when click category then get category data`enter code here`
import React, { Component, useEffect, useState } from 'react'`enter code here`;
import Thumnailport_list from './Thumnailport_list';
import Portlightbox from './Portlightbox';
import Functional from './Functional';
import $ from 'jquery';
const Portfolio = () => {
const filterItem = async (categoryitem) => {
const updateitmes = allModelos.filter((curElm) => {
return curElm.categories === categoryitem
})
getporfolioState(updateitmes)
}
const [getporfolio, getporfolioState] = useState([])
const [allModelos, guardarAllModelo] = useState([]);
$(document).ready(function () {
$(".grid-wrap .grid li").unbind().click(function (e) {
console.log(this.className);
var newe = this.className;
$('.' + newe).addClass('current show');
$("#grid-gallery").addClass("slideshow-open");
});
$("#closeport").unbind().click(function (e) {
$("#grid-gallery").removeClass("slideshow-open");
$(".portfolio .grid li").removeClass('current show');
$(".portfolio .slideshow ul > li").removeClass('current show');
});
});
const portadd = () => {
document.body.classList.add('portfolio');
document.body.classList.add('at-top');
document.getElementById('port').classList.add('no-transform');
document.getElementById('port').classList.add('revealator-within');
document.getElementById('port2').classList.add('no-transform');
document.getElementById('port2').classList.add('revealator-within');
document.getElementById('navbar-collapse-toggle').classList.remove('biohidemenu');
}
const getalldata = async () => {
try {
const res = await fetch("/getdata", {
method: 'Get',
headers: {
'Content-Type': 'application/json'
}
})
const data = await res.json()
// console.log("This is our data load")
// console.log(data.portfolio)
getporfolioState(data.portfolio)
guardarAllModelo(data.portfolio)
} catch (error) {
console.log(error)
// history.push("/backoffice/login")
}
}
useEffect(() => {
getalldata()
portadd()
}, []);
return (
<>
<section id="port" class="title-section text-left text-sm-center revealator-slideup revealator-once revealator-delay1">
<h1 >my <span>portfolio</span></h1>
<span class="title-bg">works</span>
</section>
<section id="port2" className="main-content text-center revealator-slideup revealator-once revealator-delay1">
<div class="container">
<button className="btn btn-about " onClick={() => filterItem('mobileapp')}>Mobile</button>
<button className="btn btn-about " onClick={() => filterItem('frontend')}>Frontend</button>
<button className="btn btn-about " onClick={() => filterItem('gdesign')}>Graphics</button>
</div>
<div id="grid-gallery" className="container grid-gallery">
{/* Portfolio Grid Starts */}
<section className="grid-wrap">
<ul className="row grid">
{
getporfolio.map((getdata, index) => {
return (
<>
<Thumnailport_list
key={index}
portID={getdata._id}
imagetag={getdata.imguploadedFile}
figuertext={getdata.projectname}
/>
</>
)
})
}
</ul>
</section>
{/* Portfolio Grid Ends */}
{/* Portfolio Details Starts */}
<section className="slideshow" id="sdfer">
<ul>
{/* Portfolio Item Detail Starts */}
{
getporfolio.map((getdata, index) => {
return (
<>
<Portlightbox
idlight={getdata._id}
imagelight={getdata.imguploadedFile}
langport={getdata.language}
clientport={getdata.client}
projectnameport={getdata.projectname}
previewport={getdata.preview}
/>
</>
)
})
}
</ul>
{/* Portfolio Navigation Starts */}
<nav>
{/*<span className="icon nav-prev prev"><img src="images/left-arrow.png" alt="previous" /></span>
<span className="icon nav-next next"><img src="images/right-arrow.png" alt="next" /></span>*/}
<span className="nav-close" id="closeport"><img src="images/close-button.png" alt="close" /> </span>
</nav>
{/* Portfolio Navigation Ends */}
</section>
</div>
</section>
</>
)
}
export default Portfolio;

Why is my component rendering twice without Strict Mode?

I would like to ask for some help with this, i don't know if its normal or not.
Have This components, one is a container that fetch the data and the second one receive the data and display it in a div. Nothing fancy.
const ProjectContainer = () => { // component
const projects = useSelector((state) => state.projectReducer.projects);
const count = useSelector((state) => state.projectReducer.count);
const isDarkMode = useSelector((state) => state.themeReducer.isDarkMode);
const [isLoading, setIsLoading] = useState(false);
const limit = 5;
const dispatch = useDispatch();
useEffect(() => {
console.log("INSIDE USEFFECT");
if (projects.length > 0) return; // avoid fetching data if the state has data already
async function getData() {
setIsLoading(true);
try {
const projectsCollectionRef = db.collection("project-collection");
const projectsCountRef = db
.collection("aggregation")
.doc("project-collection");
console.log("FETCHING DATA");
const responseCount = await projectsCountRef.get();
const count = await responseCount.data().count;
//dispatch
dispatch({ type: "SET_PROJECTS_COUNT", payload: count });
const response = await projectsCollectionRef
.orderBy("createdAt")
.limit(limit)
.get();
let dataSend = [];
response.forEach((document) => {
dataSend.push({ ...document.data(), uid: document.id });
});
//dispatch
dispatch({ type: "SET_PROJECTS", payload: dataSend });
setIsLoading(false);
} catch (error) {
console.error(error);
}
}
getData();
}, [dispatch, projects.length]);
return (
<div className="container mx-auto text-center">
<div>
Proyectos
</div>
{isLoading && projects.length === 0 ? (
<div >
<div id="title">
<p>
Cargando....
</p>
</div>
</div>
) : (
<>
{projects.length === 0 ? (
<div >
<div id="title" >
<p>
No hay proyectos que mostrar....
</p>
</div>
</div>
) : (
<>
<div >
{projects.map((project, index) => {
return (
<Project data={project} index={index} key={project.uid} />
);
})}
</div>
{count !== projects.length && (
<button>
Cargar más
</button>
)}
</>
)}
</>
)}
</div>
);
};
export default ProjectContainer;
The component that shows the data is something like this
import React from "react";
import { useSelector } from "react-redux";
const Project = (props) => {
const { data, index } = props;
console.log({ index });
const isDarkMode = useSelector((state) => state.themeReducer.isDarkMode);
return (
<div>
<div id="image">
<div>
<img
src={data.imageURL}
alt=""
/>
</div>
</div>
<div id="textblock">
<h1 >
{data.name}
</h1>
<div id="description">
<span >{data.description}</span>
<div >
<p>
Tecnologías
</p>
{data.technologies.map((technology) => {
return (
<span key={technology}>
{technology}
</span>
);
})}
</div>
<div >
<div >
<span>
Api Utilizada:
</span>
</div>
<div >
<span>
{data.usedAPI}
</span>
</div>
</div>
</div>
</div>
</div>
);
};
export default Project;
I mean, it works, it does its job, but I don't know if it's correct, in a more realistic company work it should work like this ?
I read that Strict mode can force to do some re renders, but i checked and don't have it.
At the end console looks like this ..
thanks in advance everyone :)
React will re-render once for each dispatch, even if multiple dispatch functions are called in the same cycle. This article has some good info on it:
https://medium.com/unsplash/react-redux-performance-considerations-when-dispatching-multiple-actions-5162047bf8a6
Fortunately, there is a solution: the batch function provided by Redux:
https://react-redux.js.org/api/batch
Just call both of your dispatch calls from within a batch, and you should see it only re-render once.

Categories

Resources