update text to API using ReactQuill texteditor - reactjs

Im trying to update my text in a reactquill texteditor. I also have a input where I can change the title, and it works fine. but when Im trying to set the Text from the text editor it never change.
Im getting the title and text from my update API and it works fine in postman so Im pretty sure its the text editor thats not working with me.
This is what I got so far:
function UpdateDoc() {
const routing = useNavigate();
const params = useParams();
const [name, setName] = useState()
const [text, setText] = useState()
//const quill = useRef();
useEffect(() => {
getDocDetails();
}, [])
const getDocDetails = async () => {
let res = await docModel.getOneDoc(params.id)
setName(res.name)
setText(res.text)
}
const updateDocDetails = async () => {
let res = await docModel.updateOneDoc({ name, text }, params.id)
console.log(res)
routing("/show")
}
return (
<div>
<h2>Update Doc</h2>
<>
<div className='toolbar'>
<button className="button-5" type="button" onClick={updateDocDetails} >
Update
</button>
</div>
<div className='createcontainer'>
<label>Name of Document: </label>
<input
type="text"
placeholder="Add Name of document"
value={name}
onChange={(e) => { setName(e.target.value) }}
name="name"
className="name-text"
/>
<ReactQuill
placeholder="Add text to document"
value={text}
theme="snow"
name="text"
//value="editor.getContents()"
onEditorChange={(e) => { setText(e.target.ref) }} // I FEEL LIKE IS THIS BIT THAT DOS NOT WORK FOR ME
//ref={quill}
/>
</div>
</>
</div >
)
}
export default UpdateDoc

Related

Onchange in input field is not working while editing a form

I am developing a small application in react, in which I have an edit option. On clicking the edit button, it will load the existing data and allows the user to edit any of the fields and submit.
Fetching the data and loading it in a form are working fine, but when I edit a textbox, the value changes to the existing fetched value, and it is not allowing me to hold the edited value.
Please note, the problem is with editing the input in a form not in submitting. Below is the edit component that I am using.
mport { useState, useEffect } from 'react';
import { json, Link } from 'react-router-dom';
import { useParams } from 'react-router-dom';
const EditTask = ({ onEdit }) => {
const [text, setText] = useState('');
const [day, setDay] = useState('');
const [reminder, setReminder] = useState(false);
const params = useParams();
useEffect(() => {
fetchTask();
});
const fetchTask = async () => {
const res = await fetch(`http://localhost:5000/tasks/${params.id}`);
const data = await res.json();
setText(data.text);
setDay(data.day);
setReminder(data.reminder);
};
const onSubmit = async (e) => {
e.preventdefault();
if (!text) {
alert('Please enter task name');
return;
}
onEdit({ text, day, reminder });
setText('');
setDay('');
setReminder(false);
};
const handleChange = ({ target }) => {
console.log(target.value); // displaying the input value
setText(target.value); // changes to existing value not the one I entered
};
return (
<form className="add-form" onSubmit={onSubmit}>
<div className="form-control">
<label>Task</label>
<input
id="AddTask"
type="text"
placeholder="Add Task"
value={text}
onChange={handleChange}
/>
</div>
<div className="form-control">
<label>Date & Time</label>
<input
id="Date"
type="text"
placeholder="Date & Time"
value={day}
onChange={(e) => setDay(e.target.value)}
/>
</div>
<div className="form-control form-control-check">
<label>Set Reminder</label>
<input
id="Reminder"
type="checkbox"
checked={reminder}
value={reminder}
onChange={(e) => setReminder(e.currentTarget.checked)}
/>
</div>
<input className="btn btn-block" type="submit" value="Save Task" />
<Link to="/">Home</Link>
</form>
);
};
export default EditTask;
Can someone explain what I am missing here? Happy to share other information if needed.
Expecting the input fields to get the value entered and submitting.
You missed adding dependency to useEffect
Yours
useEffect(() => {
fetchTask()
}
)
Should be changed
useEffect(()=>{
fetchTask()
}, [])
becasue of this, fetchTask is occured when view is re-rendered.

How do I store an image in react useState

I'm trying to add a form in which users can add text and images which is then going to be stored on the mongodb database. As of right now, I'm trying to add a section in the form where users can add images. I'm trying to figure out a way to store an image that the user uploads and send it to the backend (I'm using MERN stack).
This is my code that deals with the form, in terms of getting user input and sending it to the backend:
import { useState } from "react";
import { adminSDGOptions } from "./AdminCategoryLists";
import { adminAssingmentOptions } from "./AdminCategoryLists";
import { keywordsOptions } from "../FilterComponents/CategoryArrays/KeywordsOptions";
import Multiselect from "multiselect-react-dropdown"
import Select from 'react-select';
const ProjectAdminForm = () => {
// Adding basic info
const [sdg, setSDG] = useState('')
const [goal, setGoal] = useState('')
const [orginization, setOrginization] = useState('')
const [source, setSource] = useState('')
const [location, setLocation] = useState('')
const [published, setPublished] = useState('')
const [website_url, setWebsiteURL] = useState('')
const [assignment_type, setAssignmentType] = useState('')
const [sharepoint_link, setSharepointLink] = useState('')
const [statement, setStatement] = useState('')
const [preview_img, setPreviewImg] = useState([])
const [error, setError] = useState(null)
// Adding keywords
const [keywords, setKeywords] = useState([]);
const handleSubmit = async (e) => {
e.preventDefault() // Prevents refresh of page from happening
console.log('button clicked')
const project = {sdg, goal, orginization, source, location, published, website_url, assignment_type, keywords, sharepoint_link, statement, preview_img}
console.log(project)
// Sending form response to backend
const response = await fetch('/api/projects', {
method: 'POST',
body: JSON.stringify(project),
headers: {
'Content-Type': 'application/json'
}
})
const json = await response.json
// Checking for error
if (!response.ok) {
setError(json.error)
}
if (response.ok) {
// Reset form inputs back to empty string
setSDG('')
setGoal('')
setOrginization('')
setSource('')
setLocation('')
setPublished('')
setWebsiteURL('')
setAssignmentType('')
setKeywords([])
setSharepointLink('')
setStatement('')
setError(null)
alert('Project added!')
console.log('new project added', json)
}
}
return (
<form className="create project-form" onSubmit={handleSubmit}>
<h2 style={{"textAlign": "center"}}>Add a New Project</h2>
<hr></hr>
<label>Sustainable Development Goal:</label>
<Select
className="basic-single"
classNamePrefix="select"
placeholder="Select"
name="color"
options={adminSDGOptions}
onChange={(selection) => setSDG(selection.value)}
required
/>
<label>Description:</label>
<input
type="text"
onChange={(e) => setGoal(e.target.value)}
value={goal}
required
/>
<label>OPTIONAL - Organization:</label>
<input
type="text"
onChange={(e) => setOrginization(e.target.value)}
value={orginization}
/>
<label>OPTIONAL - Source:</label>
<input
type="text"
onChange={(e) => setSource(e.target.value)}
value={source}
/>
<label>OPTIONAL - Location:</label>
<input
type="text"
onChange={(e) => setLocation(e.target.value)}
value={location}
/>
<label>Published (YEAR ONLY):</label>
<input
type="text"
onChange={(e) => setPublished(e.target.value)}
value={published}
required
/>
<label>OPTIONAL - Website URL:</label>
<input
type="text"
onChange={(e) => setWebsiteURL(e.target.value)}
value={website_url}
/>
<label>Assignment Type:</label>
<Select
className="basic-single"
classNamePrefix="select"
placeholder="Select"
name="color"
options={adminAssingmentOptions}
onChange={(selection) => setAssignmentType(selection.value)}
required
/>
<hr></hr>
<label>Enter Keyword(s):</label>
<Multiselect
className="multiselect-admin"
isObject={false}
onRemove={(selection) => setKeywords(selection)}
onSelect={(selection) => setKeywords(selection)}
options={keywordsOptions}
required
/>
<hr></hr>
<label>OPTIONAL - Statement (ONLY Assessment Ideas and Discussion Topics):</label>
<input
type="text"
onChange={(e) => setStatement(e.target.value)}
value={statement}
/>
<label>OPTIONAL - Qualtrics Link (ONLY Mini Case Study):</label>
<input
type="text"
onChange={(e) => setSharepointLink(e.target.value)}
value={sharepoint_link}
/>
// THIS IS THE SECTION I'M TRYING TO ADD AND AM NOT SURE HOW TO GO ABOUT DOING SO
<label>OPTIONAL - Preview image:</label>
<input
type="file"
name="preview_img"
accept="image/*"
onChange={(e) => setPreviewImg(e.target.value)}
/>
<div className="add-proj">
<button>Add Project</button>
</div>
{error && <div className="error">{error}</div>}
</form>
)
}
export default ProjectAdminForm
The main thing I'm trying to get working is the preview_img stuff, I'm able to ask the user for an image through <input/> but then when I store itin my useState which is set up like this const [preview_img, setPreviewImg] = useState([]), it doesn't save the actual image, rather a string which looks like this:
preview_img: "C:\\fakepath\\banner2 (2).jpg"
I'm not sure how to save the actual image and then send it to the backend in my handleSubmit function since it appears I can't just include the state name (preview_img) in the object I'm sending to the backend.
You can reach and upload the image in onChange function. If you want to use it by accessing local url, you can create and store its local url in a state.
const [imageURL,setImageURL] = useState()
onChange={(event) => {
let file = event.target.files[0]
yourUploadFunction(file, url)
setImageURL(URL.createObjectURL(file))
}}

how can i show the upload image on screen

in this, I have uploaded the image but I want to preview the image before uploading it how can I do that in react js.can any one give me the help by giving the answer or by giving me a sample program I am posting my code can anyone help me with it I am stuck with it for a long time. The code is given below:
const { REACT_APP_SERVER_URL } = process.env;
function UserForm(props) {
const {
register,
handleSubmit,
formState: { errors },
setValue,
} = useForm({ defaultValues: props.item });
const [items, setItems] = useState([]);
const getRoleData = () => {
const baseURL = `${REACT_APP_SERVER_URL}/apis/role/all`;
axios.get(baseURL).then((response) => {
setItems(response.data.data);
});
};
useEffect(() => {
getRoleData();
}, []);
const uploadPhoto = (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.onloadend = () => {
setValue('photo', reader.result);
};
reader.readAsDataURL(file);
}
return (
<form className="userForm">
<div className="form-group">
<label htmlFor="photo">Profile Photo</label>
<input
type="file"
accept=".png, .jpg, .jpeg"
className="form-control"
name="photo"
onChange={(e) => uploadPhoto(e)}
placeholder="Enter your office photo "
// {...register("photo")}
/>
{errors.photo && (
<p className="text-danger">Photo is required</p>
)}
</div>
<div className="form-group mt-4">
{!props.viewItem && props.view && (
<Button
onClick={handleSubmit(props.submitHandler)}
variant="contained"
className="btn1"
>
{props.editItem ? "Update" : "Add"}
</Button>
)}
<Button
variant="contained"
className="btn1"
onClick={() => {
props.setShowAddUser(false);
props.setItem("");
}}
>
Cancel
</Button>
</div>
</form>
);
}
export default UserForm;
import {useState } from "react";
// useState
const [file, setFile] = useState("");
// input
<input
type="file"
id="file"
onChange={(e) => setFile(e.target.files[0])}
/>
// preview
<img src={file ? URL.createObjectURL(file) : "https://default-image.jpg"} alt="" />

How to display a ref variable without using state in React?

was wondering if there is any way to directly display the value of a variable from ref without using state, all the examples deal with "alerting" and alert works just fine, I'm trying to figure out to way to display it immediately as well. So, I am simply trying to display the value from the "name" here. Apologies for the x variable naming.
I assume it's not friendly to the DOM.
Thank you.
const UncontrolledExample = () => {
const name = useRef();
let x = '';
const showValue = (e) => {
e.preventDefault();
alert(name.current.value);
x = name.current.value;
return x;
};
return (
<div>
<label>
<input type="text" ref={name}/>
</label>
<button onClick={showValue}>
Display value : {x}
</button>
</div>
)
}
In react, if you want the page to update, you must set state. Your tutorial seems to be showing you how to do uncontrolled components. If you want to keep the input as an uncontrolled component you can, but you still need a state for X. That would look like this:
const UncontrolledExample = () => {
const name = useRef();
const [x, setX] = useState('');
const showValue = (e) => {
e.preventDefault();
setX(name.current.value);
};
return (
<div>
<label>
<input type="text" ref={name}/>
</label>
<button onClick={showValue}>
Display value : {x}
</button>
</div>
)
}
Alternatively, you can turn the input into a controlled component. If you want the display value to only change when the button is pressed, you'll need two states:
const ControlledExample = () => {
const [inputValue, setInputValue] = useState('');
const [x, setX] = useState('');
const showValue = (e) => {
e.preventDefault();
setX(inputValue);
};
return (
<div>
<label>
<input type="text"
value={inputValue}
onChange={(e) => setInputValue(e.currentTarget.value)}
/>
</label>
<button onClick={showValue}>
Display value : {x}
</button>
</div>
)
}
If they should always change simultaneously (ie, without the button), you just need one state:
const ControlledExample = () => {
const [inputValue, setInputValue] = useState('');
return (
<div>
<label>
<input type="text"
value={inputValue}
onChange={(e) => setInputValue(e.currentTarget.value)}
/>
</label>
<p>Display value : {inputValue}</p>
</div>
)
}

Trying to bind submit and save to localStorage

Here my App.js code, I am trying to bind and capture the "handlesubmit" function, and then append to an empty list which will be populated. Thanks.
import React from 'react';
const App = () => {
const [songs, setSongs] = React.useState([]);
React.useEffect(() => {
const data = localStorage.getItem('songs');
if (!data) { }
setSongs(JSON.parse(data));
}, []);
React.useEffect(() => {
localStorage.setItem('songs', JSON.stringify(songs));
});
const handleSubmit = data => {
setSongs([data]);
}
return (
<main>
<h1>Music Editor</h1>
<form onSubmit={this.props.handleSubmit(this.handleSubmit.bind(this))} autoComplete="false">
<label for="title">Title:</label>
<input type="text" id="title" name="title" placeholder="Type title/name of song" value="" />
<input type="submit" value="Add song" />
</form>
</main>
);
}
export default App;
The explanation is commented in the code itself.
Here is the codesandbox link to see the App working.
import React from 'react';
const App = () => {
const [songs, setSongs] = React.useState([]);
// use another state for song title
const [songTitle, setSongTitle] = React.useState('');
React.useEffect(() => {
const data = localStorage.getItem('songs');
// only update the state when the data persists
if (data) setSongs(JSON.parse(data));
}, []);
// update the localStorage whenever the songs array changes
React.useEffect(() => {
localStorage.setItem('songs', JSON.stringify(songs));
}, [songs]);
// inside the functional component, there is no "this" keyword
const handleSubmit = (event) => {
event.preventDefault();
// append the new song title with the old one
setSongs([
...songs,
songTitle
]);
}
return (
<main>
<h1>Music Editor</h1>
<form onSubmit={handleSubmit} autoComplete="false">
<label htmlFor="title">Title:</label>
<input
type="text"
id="title"
name="title"
placeholder="Type title/name of song"
value={songTitle}
onChange={e => setSongTitle(e.target.value)}
/>
<input type="submit" value="Add song" />
</form>
</main>
);
}
export default App;

Resources