After getting results from api call to Google books i'd like to hide the description paragraphs and have a toggle button using the css class of hidden (tailwinds css). I'm currently just console.logging the elements on the "view description" button & I'm just not sure how to target a single element after looping through the nodeList with my toggleDesc() function
React SearchBar component
import React, { useState, useEffect } from 'react';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import axios from 'axios';
import { faSearch } from '#fortawesome/free-solid-svg-icons';
import SearchResult from '../search-result/search-result.component';
const SearchBar = () => {
const [searchTerm, setSearchTerm] = useState('');
const [books, setBooks] = useState({ items: [] });
useEffect(() => {
async function fetchBooks() {
const newRes = await fetch(`${API_URL}?q=${searchTerm}`);
const json = await newRes.json();
const setVis = Object.keys(json).map(item => ({
...item, isDescVisible: 'false'
}))
setBooks(setVis);
}
fetchBooks();
}, []);
const toggleDesc = (id) => {
const newBooks = books.items.map(book => book.id === id ? {...book, isDescVisible: !book.isDescVisible} : book);
console.log(newBooks);
setBooks(newBooks);
}
const onInputChange = (e) => {
setSearchTerm(e.target.value);
};
let API_URL = `https://www.googleapis.com/books/v1/volumes`;
const fetchBooks = async () => {
// Ajax call to API via axios
const result = await axios.get(`${API_URL}?q=${searchTerm}`);
setBooks(result.data);
};
// Handle submit
const onSubmitHandler = (e) => {
// prevent browser from refreshing
e.preventDefault();
// call fetch books async function
fetchBooks();
};
// Handle enter press
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
e.preventDefault();
fetchBooks();
}
}
return (
<div className="search-bar p-8">
<div className="bg-white flex items-center rounded-full shadow-xl">
<input
className="rounded-l-full w-full py-4 px-6 text-gray-700 leading-tight focus:outline-none"
id="search"
type="text"
placeholder="Try 'The Hunt For Red October by Tom Clancy' "
onChange={onInputChange}
value={searchTerm}
onKeyPress={handleKeyPress}
/>
<div className="p-4">
<button
onClick={onSubmitHandler}
className="bg-blue-800 text-white rounded-full p-2 hover:bg-blue-600 focus:outline-none w-12 h-12 flex items-center justify-center"
>
<FontAwesomeIcon icon={faSearch} />
</button>
</div>
</div>
<div className='result mt-8'>
<ul>
<SearchResult books={books} toggleDesc={toggleDesc} />
</ul>
</div>
</div>
);
};
export default SearchBar;
SearchResults Component
import React from 'react';
import { LazyLoadImage } from 'react-lazy-load-image-component';
import 'react-lazy-load-image-component/src/effects/blur.css';
import './search-result.styles.scss';
const SearchResult = ({ books, toggleDesc }) => {
return (
<div className="search-result mb-6">
{books.items !== undefined &&
books.items !== null &&
books.items.map((book, index) => {
return (
<div key={index} className="book-info mb-2">
<li className="ml-4">
<div className="flex">
<LazyLoadImage
className="book-img px-4 py-2"
effect="blur"
alt={`${book.volumeInfo.title} book`}
src={`http://books.google.com/books/content?id=${book.id}&printsec=frontcover&img=1&zoom=1&source=gbs_api`}
/>
<div className="flex-1">
<h3 className="text-2xl">{book.volumeInfo.title}</h3>
<div>
<p className="flex">
<button
onClick={() => toggleDesc(book.id)}
className="bg-blue-800 mt-2 text-gray-200 rounded hover:bg-blue-400 px-4 py-3 text-sm focus:outline-none"
type="button"
>
View Description
</button>
</p>
{book.isDescVisible &&
<div
className="block border px-4 py-3 my-2 text-gray-700 desc-content"
>
<p>{book.volumeInfo.description}</p>
</div>
}
</div>
<h3 className="text-xl text-blue-800 mt-2 p-2">
Average time to read:{' '}
</h3>
</div>
</div>
<hr />
</li>
</div>
);
})}
</div>
);
};
export default SearchResult;
console
You will have to add a property to each item of your books to handle the description visibility and change it when you click the button, this is a basic example
useEffect(()=> {
fetch(url).then(res => {
const newRes = res.map(item=> ({ ...item, isDescVisible: 'false' })) // <— add the new property to all items set to false
setBooks(newRes);
})
})
<p className='flex'>
<button
onClick={() => toggleDesc(book.id)} // <—- pass the id or the whole book
className='bg-blue-800 mt-2 text-gray-200 rounded hover:bg-blue-400 px-4 py-3 text-sm focus:outline-none'
type='button'
>
View Description
</button>
</p>
//here show the desc according to the value of the property you added, no need for the hidden class
{book.isDescVisible && <div className='block border px-4 py-3 my-2 text-gray-700 desc-content'>
<p>{book.volumeInfo.description}</p>
</div>}
This function needs to be on the parent where you are setting the state
const toggleDesc = (id) => {
const newBooks = books.map(book => book.id === id ? {...book, isDescVisible: !book.isDescVisible} : book); <-- toggle the property
setBooks(newBooks); <—- save it in the state again
};
Related
I am loading data from firebase, so when I refresh, it takes time to load it. And added data are not present in the cart that,s why I am not getting any product in the cart. But I did follow the same process to store user data, and it,s working fine, which means I am getting a registered profile in console. Can anyone suggest me a solution for getting data in the cart?
sending data:
import { motion } from "framer-motion";
import React, { useEffect, useRef, useState } from "react";
import { MdShoppingBasket } from "react-icons/md";
import { actionType } from "../context/reducer";
import { useGlobalState } from "../context/stateProvider";
import NotFound from "../img/NotFound.svg";
const RowContainer = ({ flag, data, scrollValue }) => {
const [{ cartItems }, dispatch] = useGlobalState();
const [items, setItems] = useState([]);
const rowContainer = useRef();
const addToCart = () => {
dispatch({
type: actionType.SET_CARTITEMS,
cartItems: items,
});
localStorage.setItem("cartItems", JSON.stringify(items));
};
useEffect(() => {
addToCart();
}, [items]);
useEffect(() => {
rowContainer.current.scrollLeft += scrollValue;
}, [scrollValue]);
return (
<div
ref={rowContainer}
className={`w-full my-12 flex items-center ${
flag
? "overflow-x-scroll scrollbar-none scroll-smooth"
: "overflow-x-hidden flex-wrap justify-center"
}`}
>
{data && data.length > 0 ? (
data.map((item) => {
const { id, price, imageURL, calories, title } = item;
return (
<div
key={id}
className="w-350 min-w-[300px] md:min-w-[380px] md:my-10 backdrop-blur-lg mx-1 my-2 lg:mx-2 "
>
<div className="w-full flex flex-row items-center justify-between bg-white rounded-lg drop-shadow-lg py-2 px-4 hover:bg-whiteAlpha min-h-[150px]">
<motion.img
whileHover={{ scale: 1.2 }}
src={imageURL}
alt="img"
className="w-30 max-h-40 -mt-8 duration-100 drop-shadow-2xl"
/>
<div className="flex flex-col items-end justify-end gap-4">
<motion.div
whileTap={{ scale: 0.75 }}
className="w-8 h-8 rounded-md bg-orange-500 hover:bg-orange-600 "
onClick={() => setItems([...new Set(cartItems), item])}
>
<MdShoppingBasket className="text-white text-2xl m-1" />
</motion.div>
<div className=" w-full">
<p className="text-gray-800 md:text-lg text-base text-right">
{title}
</p>
<p className="text-sm text-gray-500 text-right">
<span className="text-orange-600">$</span> {price}
</p>
</div>
</div>
</div>
</div>
);
})
) : (
<div className="w-full flex flex-col items-center justify-center">
<img src={NotFound} className="h-340" alt="" />
<p className="text-center my-2 text-xl text-red-500">No data found</p>
</div>
)}
</div>
);
};
export default RowContainer;
fetching data
export const fetchCart = () => {
const cartInfo =
localStorage.getItem("cartItems") !== "undefined"
? JSON.parse(localStorage.getItem("cartItems"))
: localStorage.clear();
return cartInfo ? cartInfo : [];
};
You are clearing your data for no reason
localStorage.getItem("cartItems") !== "undefined"
should be
localStorage.getItem("cartItems") !== undefined
I have create a refinement component that sends data to its parent and it works correctly. after data goes to parent component, it will save to an array with useState. array value is ok when data from child component is incremental, but when the value from child component is decremented, the array value is not correct.
Here's the code:
Refinement.jsx
import { Fragment, useState } from "react";
const Refinement = (props) => {
let [fileTypeSelected, setFileTypeSelected] = useState([]);
let changingState = "";
const CheckBoxHandler = (event, content) => {
if (event) {
fileTypeSelected.push(content);
changingState = "Incremental"
}
else {
fileTypeSelected = fileTypeSelected.filter((c) => c !== content);
changingState = "Decremental"
}
}
return (
<Fragment>
<div className="w-full rounded-md overflow-hidden shadow-sm border">
<div className="flex justify-between items-center px-4 py-1 bg-biscay-700 text-white border-b">
<span className="font-semibold ">{props.RefineName}</span>
</div>
{
<div className={`px-4 py-2 w-full flex flex-col gap-2 transform transition-all duration-200 ${props.RefineValue.length <= 5 ? "" : "h-36 overflow-y-scroll scrollbar"} `}>
{
props.RefineValue.map(m => {
return (
<div className="text-sm flex justify-between items-center" key={m.id}>
<span>{m.displayName}</span>
<input className="accent-sky-500 w-4 h-4 rounded-md" onChange={(event) => {
CheckBoxHandler(event.target.checked, m.displayName);
props.onDataModified({
SearchCompnent: props.RefineName,
SearchItem: fileTypeSelected,
SearchState: changingState
});
}} type="checkbox" name="" id="" />
</div>
)
})
}
</div>
}
</div>
</Fragment>
)
}
export default Refinement;
App.jsx
import { Fragment, useState } from "react";
import Refinement from "../components/Refinement";
const App = () => {
const [fileFormatRefine, setfileFormatRefine] = useState([
{ id: 0, displayName: 'PDF' },
{ id: 1, displayName: 'DOCX' },
{ id: 2, displayName: 'PPTX' },
{ id: 3, displayName: 'XLSX' },
{ id: 4, displayName: 'TXT' },
{ id: 5, displayName: 'MP3' },
{ id: 6, displayName: 'MP4' },
{ id: 7, displayName: 'CS' },
]);
const [filterFormatModifiedDate, setFilterFormatModifiedDate] = useState([]);
let FileFormatQueryTemp = [];
const FileFormatModifiedEnvent = (enterdModifiedData) => {
const modifiedData = {
...enterdModifiedData
};
FileFormatQueryTemp = [];
for (let index = 0; index < modifiedData.SearchItem.length; index++) {
FileFormatQueryTemp.push([[modifiedData.SearchCompnent, modifiedData.SearchItem[index]]]);
}
setFilterFormatModifiedDate([]);
console.log(modifiedData.SearchItem.length);
setFilterFormatModifiedDate(FileFormatQueryTemp);
}
return (
<Fragment>
<div className="w-full lg:w-5/6 mx-auto flex gap-4 mt-16 px-4">
<div className="w-1/4 col-start-1 hidden lg:flex">
<form className="flex flex-col gap-4 w-full" id="Form" onSubmit={(event) => { event.preventDefault() }}>
<Refinement onDataModified={FileFormatModifiedEnvent} MinToShow={3} RefineValue={fileFormatRefine} RefineName="File Format"></Refinement>
<button className="h-8 text-white font-semibold text-sm rounded bg-red-600" onClick={() => { console.log(filterFormatModifiedDate.length) }}>Show Array Length</button>
</form>
</div>
<div className="lg:w-3/4 w-full flex flex-col gap-2">
<div className="w-full">
<h3 className="text-xs flex items-center font-semibold uppercase mb-2">Filters
<span className="h-4 w-4 ml-2 text-xs flex items-center justify-center rounded bg-gray-200 text-black">{filterFormatModifiedDate.length}</span>
</h3>
<div className="">
{
filterFormatModifiedDate.map(f => {
return (
<p key={f[0][1]} >{f[0]}</p>
)
})
}
</div>
</div>
</div>
</div>
</Fragment>
)
}
export default App;
if you wanna change fileTypeSelected state, you should do next:
setFileTypeSelected(prevArray => [...prevArray, content])
and in else scope:
setFileTypeSelected(prevValue => prevValue.filter((c) => c !== content));
You must always change state using his function, which comes inside array as second argument
let's consider this example
const [count,setCount] = useState(0)
setCount is the only function that can change count value
I am trying to have it so that the background of my weather app will change based on the weather condition using nextjs and the current weather data API. But no image is display. This is my Main
import axios from "axios";
import { useState } from "react";
import Weather from "./Weather";
import Spinner from "./Spinner";
import { data } from "autoprefixer";
import Background from "./Background";
const Main = () => {
const [city, setCity] = useState("");
const [weather, setWeather] = useState({});
const [loading, setLoading] = useState(false);
//In celsius -(&units=metric) in fahrenheit -(&units=imperial)
const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${process.env.NEXT_PUBLIC_WEATHER_KEY}`;
const fetchWeather = (e) => {
e.preventDefault();
setLoading(true);
axios.get(url).then((response) => {
setWeather(response.data);
// console.log(response.data);
});
setCity("");
setLoading(false);
};
if (loading) {
return <Spinner />;
} else {
return (
<div>
{/* Overlay, so we use a self-closing div */}
<div className="absolute top-0 left-0 right-0 bottom-0 bg-black/40 z-[1]" />
<Background
weatherDescription={data.weather ? data.weather[0].main : null}
/>
<div className="relative flex justify-between items-center max-w-[500px] w-full m-auto pt-4 text-white z-10">
<form
onSubmit={fetchWeather}
className="flex justify-between items-center w-full m-auto p-3 bg-transparent border border-gray-300 text-white rounded-2xl"
>
<div>
<input
onChange={(e) => setCity(e.target.value)}
className="bg-transparent border-none text-white focus:outline-none text-2xl"
type="text"
placeholder="Search"
/>
</div>
<button onClick={fetchWeather}>
<BsSearch size={20} />
</button>
</form>
</div>
{weather.main && <Weather data={weather} />}
</div>
);
}
};
And this is the background component
import React from "react";
import img1 from "../public/assets/Rainy weather.jpg";
import img2 from "../imgs/Cloudy Weather.jpg";
function Background(props) {
const images = [
{
name: "Rain",
background: img1,
},
{
name: "Clouds",
background: img2,
},
];
const imgURL = images.find((el) => el.name === props.weatherDescription)
?.background;
return (
<div className="-z-10">
<img
src={imgURL}
className="object-cover w-full min-h-scren"
key={imgURL}
/>
</div>
);
}
export default Background;
I've tried if statements and functions, but nothing is working, I've found this current template that was working with videos, I've tried to change it to use images, but I can't achieve it. I'm fairly new in coding, so I hope someone can help me.
From firebase I fetch data and map this data to be shown in cards, every card has edit component and CardComponent(edit component parent) which use ref provided from useHandleOpen custom hook
Error message:
Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Component where ref is in use
export default function EditCard(id) {
const { ref, isOpen, setIsOpen } = useHandleOpen(false);
return (
<div>
<GoKebabVertical
ref={ref}
className="cursor-pointer "
onClick={() => setIsOpen(true)}
/>
{isOpen && (
<div
ref={ref}
className="w-20 h-15 bg-white z-30 rounded-md absolute text-center
top-0 right-0
"
>
<p className="hover:bg-blue-300 hover:text-white cursor-pointer">
Edytuj
</p>
<p
className="bg-red-400 text-white font-semibold hover:bg-red-600 cursor-pointer"
onClick={() => {}}
>
Usuń
</p>
</div>
)}
</div>
);
}
export const Edit = memo(EditCard);
Card component which use ref tho and its Edit parent
const Card = ({ data, id }) => {
const editRef = useRef(null);
const { ref, isOpen, setIsOpen } = useHandleOpen(editRef);
return (
<div
className="bg-gradient-to-r from-blue-200 to-purple-500
w-64 h-28 rounded-md relative
"
>
<div className="relative top-0 left-0">
<p className="px-2 pt-1 font-bold text-gray-800 text-lg">
{data.subject_name}
</p>
<p className="px-2 text-xs text-gray-800">Sala 101</p>
</div>
<div
className="absolute top-0 right-0 rounded-r-md
rounded-b-none
bg-white w-6 h-7
grid place-items-center
"
>
<Edit id={id} />
</div>
<div className="absolute bottom-9 left-0 mb-2.5">
<p className="px-2 text-xs text-gray-800">{data.teacher}</p>
</div>
<div className=" flex direction-row mt-7 text-center w-full justify-end align-bottom pr-2 ">
<div className="rounded-lg w-14 h-7 mx-3 bg-purple-300">
<a
href={data.link_subject}
className="text-gray-800
"
target="_blank"
rel="noreferrer"
>
Lekcja
</a>
</div>
<div className="rounded-lg w-14 h-7 bg-gray-800 ">
<a
href={data.link_online_lesson}
target="_blank"
rel="noreferrer"
className="text-white"
>
Online
</a>
</div>
</div>
<div
className=" absolute bottom-0 left-0 rounded-l-md
bg-white w-7 h-6 grid place-items-center devide-solid"
>
{isOpen ? (
<AiOutlineUp
className="cursor-pointer"
ref={ref}
onClick={() => setIsOpen(true)}
/>
) : (
<AiOutlineDown
className="cursor-pointer"
ref={ref}
onClick={() => setIsOpen(true)}
/>
)}
</div>
{isOpen && (
<div
className="bg-gradient-to-r from-blue-200 to-purple-500 w-full text-left rounded-b-md p-4 "
ref={ref}
>
<p className="font-bold text-gray-800 text-sm ">Lekcje w:</p>
<p className="text-gray-800 text-sm">PN: 8-12</p>
</div>
)}
</div>
);
};
export const CardSubject = memo(Card);
Custom hook with ref:
export default function useHandleOpen() {
const [isOpen, setIsOpen] = useState(false);
const ref = useRef(null);
const handleClickOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
setIsOpen(!isOpen);
}
};
useEffect(() => {
document.addEventListener("click", handleClickOutside, !isOpen);
return () => {
document.removeEventListener("click", handleClickOutside, !isOpen);
};
});
return { ref, isOpen, setIsOpen };
}
Edit: Tried change it this way, but this displays warning too.
export default function useHandleOpen(ref) {
const [isOpen, setIsOpen] = useState(false);
const handleClickOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
setIsOpen(!isOpen);
}
};
useEffect(() => {
document.addEventListener("click", handleClickOutside, !isOpen);
return () => {
document.removeEventListener("click", handleClickOutside, !isOpen);
};
});
return { ref, isOpen, setIsOpen };
}
And use hook like this:
const editRef = useRef(null);
const { ref, isOpen, setIsOpen } = useHandleOpen(editRef);
Ok i fixed it by removing ref from places where i use onClick method for changing the state
I'm new in React and state hooks.I'm trying to make a website about creating booklist and save it to local storage. Also uploading image to cloudinary. My problem is ; when i trying to save cloudinary image url to the localstorage, it saves previous url. I think i have a problem about useState hooks but i couldnt figure it. Below is my code.
LocalStorage.js
import React, { useState, useEffect } from 'react'
import BookList from '../../components/BookList'
import CreateBook from '../../components/CreateBook'
const getLocalStorage = () => {
let list = localStorage.getItem('liste')
if (list) {
return JSON.parse(localStorage.getItem('liste'))
} else {
return []
}
}
const LocalStorage = () => {
//state hooks
const [list, setList] = useState(getLocalStorage)
const [bookName, setBookName] = useState('')
const [writerName, setWriterName] = useState('')
const [pageNumber, setPageNumber] = useState('')
const [info, setInfo] = useState('')
const [image, setImage] = useState('')
const [uploadUrl, setUploadUrl] = useState('')
let id
//Function for submit button
const handleSubmit = async (e) => {
e.preventDefault()
// conditions for fill the blanks
if (!bookName || !writerName || !pageNumber || !image) {
setInfo('Please fill the blanks')
} else {
try {
const data = new FormData()
data.append('file', image)
data.append('upload_preset', 'book-list-project')
data.append('cloud_name', 'book-list')
let response = await fetch(
'https://api.cloudinary.com/v1_1/book-list/image/upload',
{
method: 'POST',
body: data,
}
)
let result = await response.json()
setUploadUrl(result.url)
id = new Date().getTime().toString()
const newBook = {
id: id,
bookName: bookName,
writerName: writerName,
pageNumber: pageNumber,
uploadUrl: uploadUrl,
}
setList([...list, newBook])
setBookName('')
setWriterName('')
setPageNumber('')
setInfo('Book created')
setImage('')
} catch (error) {
console.log(error)
}
}
}
//Function for remove specific book from local storage
const removeSpecificBook = (id) => {
setList(list.filter((book) => book.id !== id))
}
// Function for clear all books from local storage
const removeAllBooks = () => {
setList([])
}
useEffect(() => {
localStorage.setItem('liste', JSON.stringify(list))
}, [list])
return (
<div>
<CreateBook
bookName={bookName}
writerName={writerName}
pageNumber={pageNumber}
handleSubmit={handleSubmit}
info={info}
setBookName={setBookName}
setWriterName={setWriterName}
setPageNumber={setPageNumber}
setImage={setImage}
/>
<BookList
items={list}
removeSpecificBook={removeSpecificBook}
removeAllBooks={removeAllBooks}
/>
</div>
)
}
export default LocalStorage
Booklist.js
import React from 'react'
const BookList = ({ items, removeSpecificBook, removeAllBooks }) => {
return (
<div className='container mx-auto'>
<div className='mt-20 flex flex-wrap items-center justify-center'>
{items.map((item) => {
return (
<div key={item.id} className='p-2 m-2 bg-yellow-100 w-1/4'>
<div className='p-1 m-1 flex justify-center'>
<img
className='object-contain h-52 w-52'
src={item.uploadUrl}
alt='some img'
/>
</div>
<div className='p-1 m-1'>
<h5 className='font-semibold'>Book Name</h5>
<h3>{item.bookName}</h3>
</div>
<div className='p-1 m-1'>
<h5 className='font-semibold'>Writer Name</h5>
<h3>{item.writerName}</h3>
</div>
<div className='p-1 m-1'>
<h5 className='font-semibold'>Total Page</h5>
<h3>{item.pageNumber}</h3>
</div>
<div className='flex justify-end'>
<button
onClick={() => removeSpecificBook(item.id)}
className='px-4 py-2 bg-red-500 rounded-full text-white'
>
Remove
</button>
</div>
</div>
)
})}
</div>
{items.length > 1 && (
<div className='flex justify-center my-5'>
<button
onClick={removeAllBooks}
className='px-8 py-4 bg-red-500 rounded-full text-white'
>
Remove All
</button>
</div>
)}
</div>
)
}
export default BookList
CreateBook.js
import React from 'react'
const CreateBook = ({
bookName,
writerName,
pageNumber,
handleSubmit,
info,
setBookName,
setWriterName,
setPageNumber,
setImage,
}) => {
return (
<div>
<div>
<nav className='bg-blue-500 text-center text-white px-6 py-3'>
Create Book
</nav>
</div>
<div className='bg-red-200 mx-auto w-96 rounded-lg flex justify-center mt-20'>
<form onSubmit={handleSubmit}>
<div>
<div className='p-3 text-center'>
<h6>Enter Book Name</h6>
<input
value={bookName}
onChange={(e) => setBookName(e.target.value)}
className='rounded-md'
type='text'
placeholder='Book Name'
/>
</div>
<div className='p-3 text-center'>
<h6>Enter Writer Name</h6>
<input
value={writerName}
onChange={(e) => setWriterName(e.target.value)}
className='rounded-md'
type='text'
placeholder='Writer Name'
/>
</div>
<div className='p-3 text-center'>
<h6>Enter Total Page Number </h6>
<input
value={pageNumber}
onChange={(e) => setPageNumber(e.target.value)}
className='rounded-md'
type='number'
placeholder='Page Number'
/>
</div>
<div className='p-3 text-center'>
<div>
<h6>Upload Image</h6>
</div>
<div className='p-3'>
<input
type='file'
onChange={(e) => setImage(e.target.files[0])}
/>
</div>
</div>
<div className='flex justify-center p-3'>
<button className='bg-blue-500 py-3 px-6 rounded-full text-white'>
Submit
</button>
</div>
<div className='p-3 text-center text-white'>
<h3>{info}</h3>
</div>
</div>
</form>
</div>
</div>
)
}
export default CreateBook
Also please if you have any suggestions about my code structure, tell me. I dont have any programming history and trying to learn from beginning. I need every suggestions to go further learning programming. Thank you in advance.
setUploadUrl(result.url);
id = new Date().getTime().toString();
const newBook = {
id: id,
bookName: bookName,
writerName: writerName,
pageNumber: pageNumber,
uploadUrl: uploadUrl
};
In here you are updating the uploadUrl to the newBook object. But the value of uploadUrl hold the previous record. Instead of setting from uploadUrl, set it from result.url.