how to select a displayed gifs in react js? - javascript

Hello Guys I am new in react JS , I got a Task , I which task I stuck , when I click on button Gifs is displayed but I Don't know how to select a particular Gif. Can anyone help me to Solve this Bugs.
If You Have any query please free feel to ask
App.js
I Used GIPHY API to displayed gifs. and Axiox for Fetching data
import "./App.css";
import { useEffect, useState } from "react";
import Axios from 'axios';
function App() {
const Api_key="XXX";
const Base_Url = "http://api.giphy.com/v1/gifs/search";
const [searchText,setSearchText] = useState("");
const [searchGif,setSearchGif] = useState("");
const [addText,setAddText] = useState([]);
const [gifs,setGifs] = useState([]);
const postValue = ()=>{
// Add Text
const addData = {
id:Date.now(),
name:searchText
}
console.log(addData);
setAddText([...addText,addData])
setSearchText("");
// Add Gifs
gifResponse();
}
const gifResponse = async()=>{
const response = await Axios.get(`${Base_Url}?api_key=${Api_key}&q=${searchGif}`)
// const res = await response.json();
setGifs(response.data.data);
console.log(response.data.data)
}
return (
<div className="App">
<div className="container">
<textarea
type="text"
className="textarea form-control shadow-none mt-3"
rows="15"
cols="45"
placeholder="Write Something Here..."
value={searchText}
onChange={(e)=>setSearchText(e.target.value)}
/>
<div class="input-group mb-3 mt-2">
<input
type="text"
class="form-control shadow-none inputtext"
placeholder="Search Gif..."
aria-label="Recipient's username"
aria-describedby="basic-addon2"
value={searchGif}
onChange={(e)=>setSearchGif(e.target.value)}
/>
<div class="input-group-append">
<span class="input-group-text " id="basic-addon2" onClick={postValue}>
POST & SEARCH
</span>
</div>
</div>
{
addText.map((add,index)=>{
return <h4 key={index}>{add.name}</h4>
})
}
{
gifs.map((gif)=>{
return <img src={gif.images.fixed_height.url} />
})
}
</div>
</div>
);
}
export default App;

You could add the URL of the gif to your postValue function.
First you'll need to create state for it:
const [selectedGif, setSelectedGif] = useState("");
In your Gif loop, add an onClick event to set the selected gif:
gifs.map((gif, index)=> <img src={gif.images.fixed_height.url} key={"gif-"+index} onClick={() => setSelectedGif(gif.images.fixed_height.url)} />)
Note that when you loop you should always include a key property at the root of the element you are creating.
Lastly, in your postValue function, add the selected gif:
const addData = {
id: Date.now(),
name: searchText,
gifUrl: selectedGif
}

Related

PreventDefault doesnt work in ReactJs Project

So Im going through React Course and I did exactly what I had to do but it seems that I cant execute preventDefault function on form submit and I dont really know why if anyone has any idea please let me know form keeps refreshing when submitted
import './ExpenseForm.css'
import { useState } from "react";
const ExpenseForm = () => {
const [enteredTitle, setEnteredTitle] = useState('');
const [enteredAmount, setEnteredAmount] = useState('6');
const [enteredDate, setEnteredDate] = useState('');
const titleChangeHandler = (event) => {
setEnteredTitle(event.target.value);
};
const amountChangeHandler = (event) => {
setEnteredAmount(event.target.value);
};
const dateChangeHandler = (event) => {
setEnteredDate(event.target.value);
};
//this is the funnction that handles Submit button
function submitHandler (event) {
event.preventDefault();
console.log("go")
const expenseData = {
title: enteredTitle,
amount: enteredAmount,
date: new Date(enteredDate)
}
};
return (
// this is the form and pointer to function that should execute when form is submitted
<form onSubmit={submitHandler}>
<div className="new-expense__controls">
<div className="new-expense__control">
<label>Title</label>
<input type="text" onChange={titleChangeHandler}/>
</div>
<div className="new-expense__control">
<label>Amount</label>
<input type="number" min="0.01" step="0.01" onChange={amountChangeHandler}/>
</div>
<div className="new-expense__control">
<label>Date</label>
<input type="date" min="2019-01-01" max="2022-12-31" onChange={dateChangeHandler}/>
</div>
</div>
<div className="new-expense__actions">
// this is the button that submits
<button type='submit'>Add Expense</button>
</div>
</form>
);
}
export default ExpenseForm;
I checked everything but I ant seem to solve problem at first I thought that I had syntax error but I didnt find anything...

React noob question trying to figure out how to use .forEach or .includes

task is to go through an array and check if there is a string that the user inputs into the form by using forEach or .includes
so basically just trying to filter out the array if possible if someone can show me a .map .foreach and .includes answer it would help
here is my code
import './App.css';
import wedding from "./images/wedding.jpg"
import React, { useState } from 'react'
function App() {
const [userInput , setUserInput] = useState("")
const guestList = ["Angela","Jack","Pan","James","Lara","Jason"]
function submitHandle(e){
e.preventDefault()
if(guestList.includes(e)){
console.log( `${e} is on the guest list`)
}
else{
console.log('you are not on the guest list ')
}
}
return (
<div className="App">
<h1>Are you on the guest list?</h1>
<img className="wedding" src={wedding} alt="wedding" />
<form onSubmit={submitHandle}>
<label>Type your name we will check if it is on the guestlist!</label>
<input type="text" value={userInput} onChange={e => setUserInput(e.target.value)} />
<input type="submit"/>
</form>
</div>
);
}
export default App;
Change your code to this :
import './App.css';
import wedding from "./logo.svg"
import React, { useState } from 'react'
export default function App() {
const [userInput , setUserInput] = useState("")
const guestList = ["Angela","Jack","Pan","James","Lara","Jason"]
function submitHandle(e){
e.preventDefault()
if(guestList.includes(userInput)){
console.log( `${userInput} is on the guest list`)
}
else{
console.log('you are not on the guest list ')
}
}
return (
<div className="App">
<h1>Are you on the guest list?</h1>
<img className="wedding" src={wedding} alt="wedding" />
<form onSubmit={submitHandle}>
<label>Type your name we will check if it is on the guestlist!</label>
<input type="text" value={userInput} onChange={e => setUserInput(e.target.value)} />
<input type="submit"/>
</form>
</div>
);
}
In your submitHandle function you need to check the state userInput for the input value, not the event.

How do i make the data in the input feild of my form in next js stay after refresh of the page?

I am working on a form in nextjs and i would love the data to remain the same i.e persist after the entire page as been refreshed or reloaded . Local storage doesnt work with next js , so i am looking for an alternative , i always get local storage not defined when i use it
Here is my code below
import React, { useState, useEffect, useLayoutEffect, createContext , useContext } from "react";
import { useRouter } from "next/router";
import Cookie from "js-cookie";
import { parseCookies } from "../helpers/index";
import { Formik } from "formik";
function Form() {
return (
<div>
<form action="" >
<section class="left">
<div class="input-container">
<label for="name">Full name</label>
<input type="text"/>
</div>
<div class="input-container">
<label for="age" required>
Mobile Number
</label>
<input type="text"/>
</div>
<div class="input-container">
<label for="phone">Choose password</label>
<input type="text"/>
</div>
</div>
</section>
</form>
</div>
);
}
export default Form;
With formik out of the question, to let data persist after refresh, you need to save it to localStorage ( or cookies ).
This works for NextJS (you need to test for window first)
Example as follows
const App = () => {
const [ value, setValue ] = useState({
name: '',
mobile: ''
});
useEffect(() => {
//you need to call this for nextjs, so this is performed only on client side.
if (typeof window !== 'undefined') {
let storedValue = localStorage.getItem('value');
if (storedValue) {
storedValue = JSON.parse(storedValue) || {}
// we explicitly get name and mobile value in case localStorage was manually modified.
const name = storedValue.name || ''
const mobile = storedValue.mobile || ''
setValue({ name, mobile }) //restore value from localStorage
}
}
},[])
// alternatively a betterway to handle side effect is useEffect
// useEffect(() => {
// localStorage.setItem('value', JSON.stringify(value))
// },[value])
const onChange = (e) => {
const name = e.target.name
const newValue = { ...value, [name]: e.target.value }
setValue(newValue);
localStorage.setItem('value', JSON.stringify(newValue)) //save input to localstorage
}
return (<div>
<input name="name" value={value.name} onChange={onChange} />
<input name="mobile" value={value.mobile} onChange={onChange} />
</div>
)
}
}

Pokemon Api: TypeError: Cannot read property 'type' of undefined

I'm working with the pokemon API and I'm running into trouble. Here's the original code where I first encountered the problem.
import React, {useState} from 'react';
const api = {
base: "https://pokeapi.co/api/v2/pokemon/"
}
function App() {
const [query, setQuery] = useState('');
const [pokemon, setPokemon] = useState({});
const search = evt => {
if(evt.key === "Enter") {
fetch (`${api.base}${query}`)
.then(res => res.json())
.then(result => {
setPokemon(result);
setQuery('');
console.log(result);
})
}
}
const weightConverter = weight => {
return Math.floor(weight / 10) + ".0 kg.";
}
const heightConverter = height => {
return (height / 10) + " m."
}
return (
<div className="wrapper">
<main>
<div className="pokedex-search-box">
<input
type="text"
className="pokedex-search-bar"
placeholder="Search for a Pokémon..."
onChange={e => setQuery(e.target.value)}
value={query}
onKeyPress={search}
></input>
</div>
<div>
<div className="pokedex">
<div className="pokedex-left">
{pokemon.name}
<br></br>
{pokemon.id}
</div>
<div>
<img src={pokemon.sprites.front_default}></img>
<br></br>
{pokemon.types[0].type.name}
<br></br>
{pokemon.types[1].type.name}
<br></br>
{weightConverter(pokemon.weight)}
<br></br>
{heightConverter(pokemon.height)}
</div>
</div>
</div>
</main>
</div>
);
}
export default App;
Originally this was my code, but after looking up the problem on google I realized that the react dom was loading faster than my api call since you have to input a search that will then fetch the object. Which it can't do that since you have to wait for a search input. After that, I added this little bit to check to see if the object was already called and if not set it to an empty string so that you can use the search.
{pokemon.sprites ? (
<div className="pokedex">
<div className="pokedex-left">
{pokemon.name}
<br></br>
{pokemon.id}
</div>
<div>
<img src={pokemon.sprites.front_default}></img>
<br></br>
{pokemon.types[0].type.name}
<br></br>
{pokemon.types[1].type.name}
<br></br>
{weightConverter(pokemon.weight)}
<br></br>
{heightConverter(pokemon.height)}
</div>
</div>
) : ('')}
And that worked fine, but after a few searches I come back to the same problem of "TypeError: Cannot read property 'type' of undefined." I'm new to react so I'm a little lost. I have a temporary solution that works for the first three pokemon and then it breaks after that.

Input email field onchange not setting string to state if last field

This is really weird, I am setting an email input as a string to state and I can see on react dev tools that it gets sent, but If I try to log it from another function I get empty string, the thing is that If I change the order of the inputs and the email is not the last one then it all works.
import React, { useState, useEffect, useCallback, useContext } from 'react'
import { useDropzone } from 'react-dropzone'
import context from '../provider/context'
import axios from 'axios'
const File = () => {
const { setStage, setProject, project, setUrls, urls, email, setEmail } = useContext(context)
const onDrop = useCallback((acceptedFiles) => uploadFile(acceptedFiles), [project])
const { getRootProps, isDragActive, getInputProps } = useDropzone({ onDrop })
// Set project name
const addProject = (e) => setProject(e.target.value)
// Set email address
const addEmail = (e) => setEmail(e.target.value)
// I got another function then that logs the `email` state,
// but if I do it right after typing on the email input I get empty string.
// If I invert the order, and `project` comes after the email input
// then it displays the email string just fine.
return (
<>
<ul className='list'>
<li>
<label className='label' htmlFor='upload'>
Project's Name
</label>
<input
id='upload'
value={project}
type='text'
name='project'
placeholder='e.g Great Project'
onChange={addProject}
autoFocus
/>
</li>
<li>
<label className='label' htmlFor='email'>
Your email address
</label>
<input
id='email'
type='email'
name='email'
value={email}
placeholder='Email address to send notification to'
onChange={addEmail}
/>
</li>
</ul>
<div className='fileTitle' {...getRootProps()}>
{isDragActive ? <p className='label'>Drop the file here ...</p> : handleResponse()}
<div className='file'>
<div id='drop-area' className={`drop-area ${isDragActive ? 'active' : ''}`}>
<div className={`icon ${response ? response : ''}`}></div>
</div>
<input
{...getInputProps()}
className='inputfile'
id='file'
type='file'
name='locations'
/>
</div>
<br />
<em className='info'>
* Don’t include any headers in the file, just your list of urls with{' '}
<strong>no headers</strong>.
</em>
</div>
</>
)}
export default File
The function that logs the email uses the react-dropzone plugin
// Upload file
const uploadFile = async (file) => {
console.log(email)
const formData = new FormData()
formData.append('urls', file[0])
try {
const options = {
headers: { 'content-type': 'multipart/form-data' },
params: { project, email }
}
const res = await axios.post('/api/upload/', formData, options)
setUrls(res.data.number)
setResponse('success')
setTimeout(() => setStage('process'), 1200)
} catch (err) {
setResponse(err.response.data)
}
}
Doing a simple onclick works fine
const checkEmail = () => {
console.log(email) // This works cause it takes it form the useContext
}
And then on the html
<button onClick={checkEmail}>Click here<button>
In the end I needed to add email as an array dependency to the react-drop zone useCallback so it can register that something has change on that state.
so I changed:
const onDrop = useCallback((acceptedFiles) =>
uploadFile(acceptedFiles), [project])
To
const onDrop = useCallback((acceptedFiles) =>
uploadFile(acceptedFiles), [project, email])
And that is the reason why, when I changed the project field after adding the email it was working.
Many thanks to #NateLevin who helped me find where the problem was at.

Categories

Resources