I can't Change text in the form in React - reactjs

I am Learning React and i want to work with forms. Initally i gave value "hello" in the form but i couldn't erase it and type anything in the form.
import { React, useState } from "react";
const App = () => {
const [num, setNum] = useState(0);
const handleClick = () => {
setNum(num + 1);
};
const mew = () => {
console.log("submiited");
};
return (
<div className="bg-green-500 text-center">
<h1 className="bg-red-200">
🎰 Welcome to <span> Slot Machine game</span> 🎰{" "}
</h1>
<h1></h1>
<button
onClick={handleClick}
className="bg-red-200 w-92 mt-4 mb-4 rounded-full p-2 text-center"
>
Click
</button>
<h1>{num}</h1>
<form className="form" onSubmit={mew}>
<div className="form-control">
<label htmlFor="firstName">Name : </label>
<input
className="mb-2"
type="text"
name="txt"
value="Hello"
onChange={(e) => {
console.log(e.target.value);
}}
/>
</div>
</form>
</div>
);
};
export default App;

This could be work
import React, { useState } from 'react';
import './style.css';
const App = () => {
const [num, setNum] = useState(0);
const [name, setName] = useState('Hello');
const handleClick = () => {
setNum(num + 1);
};
const mew = () => {
console.log('submiited');
};
return (
<div className="bg-green-500 text-center">
<h1 className="bg-red-200">
🎰 Welcome to <span> Slot Machine game</span> 🎰{' '}
</h1>
<h1></h1>
<button
onClick={handleClick}
className="bg-red-200 w-92 mt-4 mb-4 rounded-full p-2 text-center"
>
Click
</button>
<h1>{num}</h1>
<form className="form" onSubmit={mew}>
<div className="form-control">
<label htmlFor="firstName">Name : </label>
<input
className="mb-2"
type="text"
name="txt"
value={name}
onChange={(e) => {
setName(e.target.value);
}}
/>
</div>
</form>
</div>
);
};
export default App;

You are trying to use controlled inputs but not doing that correctly. When using controlled inputs, you feed the value in the input field, and it is your responsibility to change the value.
useState can help you do this.
const App = () => {
const [num, setNum] = useState(0);
const [textValue , setTextValue] = useState("hello");
const handleClick = () => {
setNum(num + 1);
};
const changeText = (e) => {
setTextValue(e.target.value);
}
const mew = () => {
console.log("submiited");
};
return (
<div className="bg-green-500 text-center">
<h1 className="bg-red-200">
🎰 Welcome to <span> Slot Machine game</span> 🎰{" "}
</h1>
<h1></h1>
<button
onClick={handleClick}
className="bg-red-200 w-92 mt-4 mb-4 rounded-full p-2 text-center"
>
Click
</button>
<h1>{num}</h1>
<form className="form" onSubmit={mew}>
<div className="form-control">
<label htmlFor="firstName">Name : </label>
<input
className="mb-2"
type="text"
name="txt"
value={textValue}
onChange={changeText}
/>
</div>
</form>
</div>
);
};
export default App;

Related

updating data in edit-form react

I have a kind of todo, but there are several lines in one object.
I need that when editing one of the fields and pressing the save button, the save will work.
Now, in order to save the changes, need to change all three inputs.
Here is my code in stakeblitz
App.js
function App(props) {
const [tasks, setTasks] = useState(props.tasks);
function editTask(id, newName, newTranslate, newNote) {
const editedTaskList = tasks.map((task) => {
if (id === task.id) {
return { ...task, name: newName, translate: newTranslate, note: newNote };
}
return task;
});
setTasks(editedTaskList);
}
const taskList = tasks
.map((task) => (
<Todo
id={task.id}
name={task.name}
translate={task.translate}
note={task.note}
completed={task.completed}
key={task.id}
editTask={editTask}
/>
));
return (
<div className="todoapp stack-large">
<ul
className="todo-list stack-large stack-exception"
aria-labelledby="list-heading">
{taskList}
</ul>
</div>
);
}
export default App;
I thought that the problem was with the handlers in the todo file, most likely there need to get the previous data from the state, and if the field has not been changed, then use this data as changed in the new state. I tried to do something like this but I couldn't find anything.
Todo.js
export default function Todo(props) {
const [isEditing, setEditing] = useState(false);
const [newName, setNewName] = useState('');
const [newTranslate, setNewTranslate] = useState('');
const [newNote, setNewNote] = useState('');
function handleChange(e) {
setNewName(e.target.value);
}
function handleChangeTranslate(e) {
setNewTranslate(e.target.value);
}
function handleChangeNote(e) {
setNewNote(e.target.value);
}
function handleSubmit(e) {
e.preventDefault();
if (!newName.trim()|| !newTranslate.trim() || !newNote.trim()) {
return;
}
props.editTask(props.id, newName, newTranslate, newNote);
setNewName("");
setNewTranslate("");
setNewNote("");
setEditing(false);
}
const editingTemplate = (
<form className="stack-small" onSubmit={handleSubmit}>
<div className="form-group">
<label className="todo-label" htmlFor={props.id}>
New name for {props.name}
</label>
<input
id={props.id}
className="todo-text"
type="text"
value={newName || props.name}
onChange={handleChange}
/>
<input
id={props.id}
className="todo-text"
type="text"
value={newTranslate || props.translate}
onChange={handleChangeTranslate}
/>
<input
id={props.id}
className="todo-text"
type="text"
value={newNote || props.note}
onChange={handleChangeNote}
/>
</div>
<div className="btn-group">
<button
type="button"
className="btn todo-cancel"
onClick={() => setEditing(false)}
>
Cancel
</button>
<button type="submit" className="btn btn__primary todo-edit">
Save
</button>
</div>
</form>
);
const viewTemplate = (
<div className="stack-small">
<div className="c-cb">
<label className="todo-label" htmlFor={props.id}>
{props.name}
</label>
<label className="todo-label" htmlFor={props.id}>
{props.translate}
</label>
<label className="todo-label" htmlFor={props.id}>
{props.note}
</label>
</div>
<div className="btn-group">
<button
type="button"
className="btn"
onClick={() => setEditing(true)}
>
Edit <span className="visually-hidden">{props.name}</span>
</button>
</div>
</div>
);
return <li className="todo">{isEditing ? editingTemplate : viewTemplate}</li>;
}
By trial and error, I found how to solve my problem.
It is necessary to transfer data from the array to the new state, which will be the initial data for it
Todo.js file
export default function Todo({name, translate, note, editTask, id}) {
const [isEditing, setEditing] = useState(false);
const [newName, setNewName] = useState(name);
const [newTranslate, setNewTranslate] = useState(translate);
const [newNote, setNewNote] = useState(note);

Next js - How to Update or Clear/Reset const array value?

I am Beginner to fronted development.I am working on next js project.
My task is to display result on form submit, Which i have done. Next task is to reset form and also clear/reset search result on button click. I am not able to find the solution, how do i can reset/clear that.
Here is What i have tried so far:
UPDATED
import { useForm } from 'react-hook-form';
import { useState } from "react";
import { yupResolver } from '#hookform/resolvers/yup';
import * as Yup from 'yup';
const userEndPoint = '/api/users/';
const { searchResults = [] } = [];
export default function Home() {
const [userSearchResults, setUserSearchResults] = useState({ result: [] });
const validationSchema = Yup.object().shape({
searchQuery: Yup.string()
.required('This field is required'),
});
const formOptions = { resolver: yupResolver(validationSchema) };
const { errors } = formState;
const resetFunction = async () => {
setUserSearchResults([]);
}
const onSubmitFunction = async (event) => {
console.log("search query =====> ",event.searchQuery)
const response = await fetch(userEndPoint+event.searchQuery)
const data = await response.json()
searchResults = data.results;
userSearchResults = data.results;
};
return (
<div className="card m-3">
<h5 className="card-header">Example App</h5>
<div className="card-body">
<form onSubmit={handleSubmit(onSubmitFunction)}>
<div className="form-row row">
<div className="col-6 d-flex align-items-center">
<input name="searchQuery" type="text" {...register('searchQuery')} className={`form-control ${errors.searchQuery ? 'is-invalid' : ''}`} />
<div className="invalid-feedback">{errors.searchQuery?.message}</div>
</div>
<div className="col-6">
<button type="submit" className="btn btn-primary mr-1">Search</button>
<button type="button" onClick={() => resetFunction()} className="btn btn-secondary">Clear</button>
</div>
</div>
</form>
</div>
<div className="card-body">
<p className="card-header">Search results: </p>
{userSearchResults}
{ <ul>
{ searchResults.map( result => {
const {id, name, image} = result;
return (
<li key={id} className='card'>
<h3>{name}</h3>
</li>
)
} ) }
</ul> }
</div>
</div>
);
}
Please correct me. Highly appreciated if suggest me with best practices.
Thank you!
I will assume the data returned from your API is an array of objects, please try this and let me know if that works:
export default function Home() {
const [userSearchResults, setUserSearchResults] = useState([]);
const validationSchema = Yup.object().shape({
searchQuery: Yup.string().required("This field is required"),
});
const formOptions = { resolver: yupResolver(validationSchema) };
const { errors } = formState;
const resetFunction = () => {
setUserSearchResults([]);
};
const onSubmitFunction = async (event) => {
console.log("search query =====> ", event.searchQuery);
const userEndPoint = "/api/users/";
const response = await fetch(userEndPoint + event.searchQuery);
const data = await response.json();
setUserSearchResults(data.results);
};
return (
<div className="m-3 card">
<h5 className="card-header">Example App</h5>
<div className="card-body">
<form onSubmit={handleSubmit(onSubmitFunction)}>
<div className="form-row row">
<div className="col-6 d-flex align-items-center">
<input
name="searchQuery"
type="text"
{...register("searchQuery")}
className={`form-control ${
errors.searchQuery ? "is-invalid" : ""
}`}
/>
<div className="invalid-feedback">
{errors.searchQuery?.message}
</div>
</div>
<div className="col-6">
<button type="submit" className="mr-1 btn btn-primary">
Search
</button>
<button
type="button"
onClick={() => resetFunction()}
className="btn btn-secondary"
>
Clear
</button>
</div>
</div>
</form>
</div>
<div className="card-body">
<p className="card-header">Search results: </p>
<ul>
{userSearchResults.length > 0 && userSearchResults.map((result) => {
const { id, name, image } = result;
return (
<li key={id} className="card">
<h3>{name}</h3>
</li>
);
})}
</ul>
</div>
</div>
);
}

How to add checkbox or radio button inside the map method in react component?

How to add the checkbox or radio button inside the map method. I have created question and answer app. I need to add checkbox or radio button for the answers. Below in the card component is where the question and answer is getting printed out. How can i add the radio button in there so user can check the answer.
import React, { useState, useEffect } from "react";
import { Fragment } from "react";
import "./Survey.css";
import CreateSurvey from "../modals/CreateSurvey";
import Card from "../card/Card";
const Survey = () => {
const [modal, setModal] = useState(false);
const [surveyList, setSurveyList] = useState([]);
useEffect(() => {
let arr = localStorage.getItem("surveyList");
if (arr) {
let obj = JSON.parse(arr);
setSurveyList(obj);
}
}, []);
const deleteSurvey = (index) => {
let tempList = surveyList;
tempList.splice(index, 1);
localStorage.setItem("surveyList", JSON.stringify(tempList));
setSurveyList(tempList);
window.location.reload();
};
const toggle = () => {
setModal(!modal);
};
const updateListArray = (obj, index) => {
let tempList = surveyList;
tempList[index] = obj;
localStorage.setItem("surveyList", JSON.stringify(tempList));
setSurveyList(tempList);
window.location.reload();
};
const saveSurvey = (surveyObj) => {
let tempList = surveyList;
tempList.push(surveyObj);
localStorage.setItem("surveyList", JSON.stringify(tempList));
setSurveyList(surveyList);
setModal(false);
};
return (
<Fragment>
<div className="header text-center">
<h5>Survey</h5>
<button className="btn btn-primary" onClick={() => setModal(true)}>
Create Survey
</button>
</div>
<div className="survey-container">
{surveyList &&
surveyList.map((obj, index) => (
<Card
surveyObj={obj}
index={index}
deleteSurvey={deleteSurvey}
updateListArray={updateListArray}
/>
))}
</div>
<CreateSurvey toggle={toggle} modal={modal} save={saveSurvey} />
</Fragment>
);
};
export default Survey;
//Card.js
import React, { useState } from "react";
import "./Card.css";
const Card = ({ surveyObj, deleteSurvey, index }) => {
const [modal, setModal] = useState(false);
const toggle = () => {
setModal(!modal);
};
const deleteHandler = () => {
deleteSurvey(index);
};
return (
<div>
<div className="card-wrapper mr-5">
<div className="card-top"></div>
<div className="survey-holder">
<span className="card-header">{surveyObj.name}</span>
<p className="answer"> {surveyObj.answerOne}</p>
<div className="icons">
<i className="far fa-edit edit"></i>
<i className="fas fa-trash-alt delete" onClick={deleteHandler}></i>
</div>
</div>
</div>
</div>
);
};
export default Card;
//Createsurvey.js
import React, { useState } from "react";
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap";
import { Fragment } from "react";
const CreateSurvey = ({ modal, toggle, save }) => {
const [question, setQuestion] = useState("");
const [answerOne, setAnswerOne] = useState("");
const [answerTwo, setAnswerTwo] = useState("");
const [answerThree, setAnswerThree] = useState("");
const [answerFour, setAnswerFour] = useState("");
const changeHandler = (e) => {
const { name, value } = e.target;
if (name === "question") {
setQuestion(value);
} else {
setAnswerOne(value);
}
};
const saveHandler = (e) => {
e.preventDefault();
let surveyObj = {};
surveyObj["name"] = question;
surveyObj["answerOne"] = answerOne;
surveyObj["answerTwo"] = answerTwo;
surveyObj["answerThree"] = answerThree;
surveyObj["answerFour"] = answerFour;
save(surveyObj);
};
return (
<Fragment>
<Modal isOpen={modal} toggle={toggle}>
<ModalHeader toggle={toggle}>Create a Survey Question</ModalHeader>
<ModalBody>
<form>
<div>
<div className="form-group">
<label>Survey Questions</label>
<input
type="text"
className="form-control"
value={question}
name="question"
onChange={changeHandler}
/>
</div>
</div>
<div className="mt-2">
<label>Survey Answers</label>
<div className="form-group">
<label>Answer 1</label>
<input
type="text"
className="form-control mt-2 mb-2"
value={answerOne}
name="answerOne"
onChange={changeHandler}
/>
</div>
<div className="form-group">
<label>Answer 2</label>
<input
type="text"
className="form-control mt-2 mb-2"
value={answerTwo}
name="answerTwo"
onChange={changeHandler}
/>
</div>
<div className="form-group">
<label>Answer 3</label>
<input
type="text"
className="form-control mt-2 mb-2"
value={answerThree}
name="answerThree"
onChange={changeHandler}
/>
</div>
<div className="form-group">
<label>Answer 4</label>
<input
type="text"
className="form-control mt-2 mb-2"
value={answerFour}
name="answerFour"
onChange={changeHandler}
/>
</div>
</div>
</form>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={saveHandler}>
Create
</Button>
<Button color="secondary" onClick={toggle}>
Cancel
</Button>
</ModalFooter>
</Modal>
</Fragment>
);
};
export default CreateSurvey;
What I am understanding is that you want to add multiple component in map method. You can simply do it as:
{surveyList &&
surveyList.map((obj, index) => (
<>
<Card
surveyObj={obj}
index={index}
deleteSurvey={deleteSurvey}
updateListArray={updateListArray}
/>
<input type="checkbox" name="userchoice" />
</>
))}

How do i limit the list of data being rendered for a particular list in react js

I'm trying to create an app that when the user clicks on create button a survey question with four answers gets created. The goal is that in a single list the user can maximum add up to 4 questions and a minimum of 1 question. So when the user tries to add another question after the 4th question a new survey list should be created. So one survey list can contain a maximum of four questions.
//Survey.js
import React, { useState, useEffect } from "react";
import { Fragment } from "react";
import "./Survey.css";
import CreateSurvey from "../modals/CreateSurvey";
import Card from "../card/Card";
const Survey = () => {
const [modal, setModal] = useState(false);
const [surveyList, setSurveyList] = useState([]);
useEffect(() => {
let arr = localStorage.getItem("surveyList");
if (arr) {
let obj = JSON.parse(arr);
setSurveyList(obj);
}
}, []);
// const surveyListArray = [];
// while (surveyList.length > 0) {
// surveyListArray.push(surveyList.splice(0, 3));
// }
const deleteSurvey = (index) => {
let tempList = surveyList;
tempList.splice(index, 1);
localStorage.setItem("surveyList", JSON.stringify(tempList));
setSurveyList(tempList);
window.location.reload();
};
const toggle = () => {
setModal(!modal);
};
const updateListArray = (obj, index) => {
let tempList = surveyList;
tempList[index] = obj;
localStorage.setItem("surveyList", JSON.stringify(tempList));
setSurveyList(tempList);
window.location.reload();
};
const saveSurvey = (surveyObj) => {
let tempList = surveyList;
tempList.push(surveyObj);
localStorage.setItem("surveyList", JSON.stringify(tempList));
setSurveyList(surveyList);
setModal(false);
};
return (
<Fragment>
<div className="header text-center">
<h5>Survey</h5>
<button className="btn btn-primary" onClick={() => setModal(true)}>
Create Survey
</button>
</div>
<div className="survey-container">
{surveyList &&
surveyList.map((obj, index) => (
<Card
surveyObj={obj}
index={index}
deleteSurvey={deleteSurvey}
updateListArray={updateListArray}
>
<input type="radio" name="answerOne" />
</Card>
))}
</div>
<CreateSurvey toggle={toggle} modal={modal} save={saveSurvey} />
</Fragment>
);
};
export default Survey;
//Card.js
import React, { useState } from "react";
import "./Card.css";
import EditSurvey from "../modals/EditSurvey";
const Card = ({ surveyObj, deleteSurvey, index, updateListArray }) => {
const [modal, setModal] = useState(false);
const toggle = () => {
setModal(!modal);
};
const updateSurvey = (obj) => {
updateListArray(obj, index);
};
const deleteHandler = () => {
deleteSurvey(index);
};
return (
<div>
<div className="card-wrapper mr-5">
<div className="card-top"></div>
<div className="survey-holder">
<span className="card-headers">{surveyObj.name}</span>
<span className="check">
<input type="radio" className="radio" />
<p className="answer"> {surveyObj.answerOne}</p>
</span>
<span className="check">
<input type="radio" className="radio" />
<p className="answer"> {surveyObj.answerTwo}</p>
</span>
<span className="check">
<input type="radio" className="radio" />
<p className="answer"> {surveyObj.answerThree}</p>
</span>
<span className="check">
<input type="radio" className="radio" />
<p className="answer"> {surveyObj.answerFour}</p>
</span>
<div className="icons">
<i className="far fa-edit edit" onClick={() => setModal(true)}></i>
<i className="fas fa-trash-alt delete" onClick={deleteHandler}></i>
</div>
</div>
<EditSurvey
modal={modal}
toggle={toggle}
updateSurvey={updateSurvey}
surveyObj={surveyObj}
/>
</div>
</div>
);
};
export default Card;
//CreateSurvey.js
import React, { useState } from "react";
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap";
import { Fragment } from "react";
const CreateSurvey = ({ modal, toggle, save }) => {
const [question, setQuestion] = useState("");
const [answerOne, setAnswerOne] = useState("");
const [answerTwo, setAnswerTwo] = useState("");
const [answerThree, setAnswerThree] = useState("");
const [answerFour, setAnswerFour] = useState("");
const changeHandler = (e) => {
const { name, value } = e.target;
if (name === "question") {
setQuestion(value);
} else if (name === "answerOne") {
setAnswerOne(value);
} else if (name === "answerTwo") {
setAnswerTwo(value);
} else if (name === "answerThree") {
setAnswerThree(value);
} else {
setAnswerFour(value);
}
};
const saveHandler = (e) => {
e.preventDefault();
let surveyObj = {};
surveyObj["name"] = question;
surveyObj["answerOne"] = answerOne;
surveyObj["answerTwo"] = answerTwo;
surveyObj["answerThree"] = answerThree;
surveyObj["answerFour"] = answerFour;
save(surveyObj);
};
return (
<Fragment>
<Modal isOpen={modal} toggle={toggle}>
<ModalHeader toggle={toggle}>Create a Survey Question</ModalHeader>
<ModalBody>
<form>
<div>
<div className="form-group">
<label>Survey Questions</label>
<input
type="text"
className="form-control"
value={question}
name="question"
onChange={changeHandler}
/>
</div>
</div>
<div className="mt-2">
<label>Survey Answers</label>
<div className="form-group">
<label>Answer 1</label>
<input
type="text"
className="form-control mt-2 mb-2"
value={answerOne}
name="answerOne"
onChange={changeHandler}
/>
</div>
<div className="form-group">
<label>Answer 2</label>
<input
type="text"
className="form-control mt-2 mb-2"
value={answerTwo}
name="answerTwo"
onChange={changeHandler}
/>
</div>
<div className="form-group">
<label>Answer 3</label>
<input
type="text"
className="form-control mt-2 mb-2"
value={answerThree}
name="answerThree"
onChange={changeHandler}
/>
</div>
<div className="form-group">
<label>Answer 4</label>
<input
type="text"
className="form-control mt-2 mb-2"
value={answerFour}
name="answerFour"
onChange={changeHandler}
/>
</div>
</div>
</form>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={saveHandler}>
Create
</Button>
<Button color="secondary" onClick={toggle}>
Cancel
</Button>
</ModalFooter>
</Modal>
</Fragment>
);
};
export default CreateSurvey;

Can't send uploaded image url from firebase into another components in react hooks

I can't send uploaded image url from firebase storage into another component using react hooks , can anybody help me? I'm new to the react and working on this part of code about 2 weeks and did'nt have any progress, it really annoying me.
This is main component where images url should come in order to render it
import React, { useState, useEffect} from "react";
import firebase from "firebase";
import Uploader from "./uploader";
function EditorBlog() {
const [title, setTitle] = useState("");
const [text, setText] = useState("");
const [category, setCategory] = useState("");
const [url , setUrl]= useState("");
const [items, setItems] = useState([]);
const onSubmit = (data) => {
data.preventDefault();
setItems([...items, {title, text, category , url} ]);
firebase
.firestore()
.collection('blogContent')
.add({
title,
category,
text,
url
// file
})
.then(()=>{
setTitle('')
setCategory('')
setText('')
setUrl('')
});
};
return (
<div>
<form onSubmit={onSubmit} className="col-md-6 mx-auto mt-5">
<div className="form-group">
<label htmlFor="Title">Blog Title</label>
<input
type="text"
name="title"
value={title}
onChange={(e) => setTitle(e.target.value)}
className="form-control"
id="Title"
placeholder="Arnold Schwarzneiger"
/>
</div>
<Uploader/>
<div className="form-group">
<label htmlFor="categorySelect">Select Category</label>
<select className="form-control" value={category} onChange={e => setCategory(e.target.value)} name="category" id="categorySelect">
<option>Nutrition</option>
<option>Fitness</option>
<option>Recipes</option>
<option>Succesfull Stories</option>
<option>Other</option>
</select>
</div>
<div className="form-group">
<label htmlFor="blogText">Blog Text</label>
<textarea
className="form-control"
name="text"
id="blogText"
rows="3"
value={text}
onChange={(e) => setText(e.target.value)}
></textarea>
</div>
<button
type="submit"
className="btn btn-primary offset-5"
onClick={onSubmit}
>
Save
</button>
</form>
<div className="mt-5">
{
items.map((item, index) => (
<div className="row bg-dark mx-auto ">
<div key={item.id} className="col-md-6 blogs_content mx-auto mt-5 " >
<div className="mblog_imgtop "><p>Beginner</p></div>
<img className="img-fluid editor_img " src={item.url} alt=""/>
<div className="col-md-12 rblog_txt text-center mx-auto">
<h6 className="mblog_category mx-auto m-4">{item.category}</h6>
<h2 className="blogs_title col-md-10 mx-auto">{item.title}</h2>
<div className="mt-5 mblog_innertxt col-md-11 mx-auto">{item.text}</div>
<div className="readm mt-5"><i>READ MORE</i></div>
</div>
</div>
</div>
))
}
</div>
</div>
);
}
export default EditorBlog;
this is my second component in which uploaded image url must be send into main component
import React, {useState} from "react";
import {storage} from "../../firebaseConfig";
import firebase from "firebase";
export default function Uploader() {
const [image , setImage]= useState(null);
const [url , setURL]= useState("");
const [imgURL, setImgURL] = useState('');
const [progress , setProgress]= useState(0);
const [error , setError]= useState("");
const handleChange =e =>{
const file = e.target.files[0];
if (file){
const fileType= file["type"];
const validFileType= ["image/gif", "image/png", "image/jpg", "image/jpeg"];
if (validFileType.includes(fileType)){
setError("");
setImage(file);
}else setError("Siz rasm kiritmadingiz");
}else {
setError("Iltimos faylni tanlang");
}
};
const handleUpload = props=>{
if (image){
const uploadTask =storage.ref(`images/${image.name}`).put(image);
uploadTask.on(
"state_changed",
snapshot =>{
const progress = Math.round(
(snapshot.bytesTransferred/snapshot.totalBytes)*100
);
setProgress(progress);
},
error =>{
setError(error);
},
()=>{
storage.ref("images").child(image.name).getDownloadURL().then(url=>{
setURL(url);
console.log(url);
firebase
.firestore()
.collection('images')
.add({
url
})
.then(()=>{
setURL('')
});
setProgress(0);
});
}
)
}else setError("Xatolik Iltimos rasmni yuklang")
};
return(
<div>
<form >
<div className="form-group" >
<input type="file" className="form-control" onChange={handleChange} />
<button type="button" className="btn btn-primary btn-block" onClick={handleUpload}>Upload</button>
</div>
</form >
<div>
{progress > 0 ? <progress style={{marginLeft: "15px"}} value={progress} max="100"/> :""}
</div>
<div style={{height : "100px", marginLeft: "15px", fontWeight: "600"}}>
<p style={{color: "red"}}>{error}</p>
</div>
<img src={url || 'http://via.placeholder.com/400x300'} alt="Uploaded images" height="300" width="650"/>
</div>
)
}
Using a callback, your EditorBlog component can tell the Uploader component what to do when an upload is complete.
In other words, EditorBlog passes a function called "onComplete" as a prop to Uploader. When the upload is completed, Uploader calls this function, with the URL as an argument.
EditorBlog
export default function EditorBlog() {
const [url , setUrl] = useState(null);
// ...
const handleCompletedUpload = (url) => {
setUrl(url);
}
return (
// ...
<div>
<Uploader onComplete={handleCompletedUpload} />
<img src={url || 'http://via.placeholder.com/400x300'} alt="Uploaded images" height="300" width="650" />
</div>
// ...
);
}
Uploader:
export default function Uploader({ onComplete }) {
// ...
uploadTask.on(
"state_changed", (snapshot) => {
// ... progress update
},
(error) => {
// ... error
},
() => {
// Success. Get the URL and call the prop onComplete
uploadTask.snapshot.ref.getDownloadURL().then(url => {
onComplete(url); // Call the callback provided as a prop
});
})
// ...
}
By the way: Notice how you can get the file reference from the uploadTask directly: uploadTask.snapshot.ref.getDownloadURL(). This way you don't have to create a new reference manually, like storage.ref("images").child(image.name).getDownloadURL().

Resources