How can I display item in ToDo List - reactjs

How to make todo list in react.I am following some tutorial how to work with react. This code is using input for adding item to list . How can I add item over h3 element instead input element?
This code is working perfect , I am looking for another way . Thank you
Here is full code .
import { useState } from 'react'
import { v4 as uuidV4 } from 'uuid'
const Header = () => {
const [input, setInput] = useState('')
const [todos, setTodos ] = useState([])
const onInput = (e) => {
setInput(e.target.value)
console.log(input)
}
const onFormSubmit = (e) => {
e.preventDefault()
setTodos([...todos, {id: uuidV4(), title:input, completed:false}])
setInput('')
}
return (
<section className='header'>
<h1>ToDo List</h1>
<form onSubmit={onFormSubmit}>
<input
type="text"
placeholder='Add Item'
className='input'
value={input}
required
onChange={onInput} />
<button
className='btn'
type='submit' > Add </button>
</form>
<br /><br />
<ul>
{todos.map((todo) => (
<li className='todo-list'> // here is output
// <h3> { ? } </h3> it should go todo.title
// can you show me how, pls ?
<input
type="text"
value={todo.title}
className='list'
onChange={(e)=>e.preventDefault()} />
</li>
))}
</ul>
</section>
)
};
export default Header;

Get the title of the todo from the todo object passed to .map() function.
<h3>{todo.title}</h3>
// Get a hook function
const {useState} = React;
const Header = () => {
const [input, setInput] = useState("");
const [todos, setTodos] = useState([]);
const onInput = (e) => {
setInput(e.target.value);
//console.log(input);
};
const onFormSubmit = (e) => {
e.preventDefault();
setTodos([...todos, { id: Math.random(), title: input, completed: false }]);
setInput("");
};
return (
<section className="header">
<h1>ToDo List</h1>
<form onSubmit={onFormSubmit}>
<input
type="text"
placeholder="Add Item"
className="input"
value={input}
required
onChange={onInput}
/>
<button className="btn" type="submit">
{" "}
Add{" "}
</button>
</form>
<br />
<br />
<ul>
{todos.map((todo) => (
<li className="todo-list">
<h3> {todo.title} </h3>
<input
type="text"
value={todo.title}
className="list"
onChange={(e) => e.preventDefault()}
/>
</li>
))}
</ul>
</section>
);
};
// Render it
ReactDOM.render(
<Header />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

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);

Directus and React data not submitting to API

I'm trying to submit reviews to a directus app but the review is not getting added to the data.
I can retrieve the data but cannot add.
I've checked all permissions and set the directus app to public permissions.
cannot figure out what the problem could be.
can anyone advise what could be wrong?
the api call:
import axios from 'axios';
const url = 'https://pwsbbqhj.directus.app/items/Reviews';
export const readReviews = () => axios.get(url);
export const createReview = (newReview) => axios.post(url, newReview);
the data retrieval :
import React, { useState, useEffect } from 'react';
import * as api from '../../../api';
import { FaStar } from 'react-icons/fa';
const colors = {
orange: '#e42320',
grey: '#a9a9a9',
};
function Ratings() {
const stars = Array(5).fill(0);
const [currentValue, setCurrentValue] = React.useState(0);
const [hoverValue, setHoverValue] = React.useState(undefined);
const handleClick = (value) => {
setCurrentValue(value);
};
const handleMouseOver = (value) => {
setHoverValue(value);
};
const [review, setReview] = useState({});
const [reviews, setReviews] = useState([]);
useEffect(() => {
const fetchData = async () => {
const result = await api.readReviews();
setReviews(result.data.data);
};
fetchData();
}, []);
const createReview = async (review) => {
try {
const data = await api.createReview({ review });
setReview([...reviews, data.data]);
} catch (error) {
console.log(error);
}
};
let [reviewCount, setreviewCount] = useState([]);
const setCountFxn = (no) => {
setReview(no);
console.log(no);
};
return (
<div className='col-md-12 row-testimonials'>
<div className='reviews-heading pb-5 pt-5'>
<h2>REVIEWS FROM OUR CUSTOMERS</h2>
</div>
<div
className='themesflat-carousel-box has-bullets bullet-circle has-buttons has-arrows clearfix'
data-gap={30}
data-column={3}
data-column2={2}
data-column3={1}
data-auto='false'
>
<div className='owl-carousel owl-theme'>
{reviews.map((review) => (
<div className='themesflat-testimonials style-2 align-center clearfix' key={review.id}>
<div className='testimonial-item'>
<div className='inner'>
<div className='thumb'>
<img src='assets/img/testimonials/customer-1-90x90.jpg' alt='altimage' />
</div>
<blockquote className='text'>
<div className='name-pos clearfix'>
<h6 className='name'>{review.Title}</h6>
<span className='position'></span>
</div>
<p>{review.Body}</p>
<div className='list-star'>
{Array.from({ length: review.Rating }).map((i) => (
<FaStar key={i} size={18} color={colors.orange} />
))}
</div>
<div className='m-2'>
By: <span className='name'>{review.Name}</span>
</div>
</blockquote>
</div>
</div>
</div>
))}
</div>
</div>
<div className='bg-black'>
<form>
<div className='mb-5'>
<h2>RATE OUR SERVICE</h2>
<div className='mt-5 mb-5'>
{stars.map((_, index) => {
return (
<FaStar
key={index}
size={20}
style={{
marginRight: 10,
cursor: 'pointer',
}}
color={(hoverValue || currentValue) > index ? colors.orange : colors.grey}
onClick={() => {
setReview({ ...review, Rating: index + 1 });
}}
onMouseOver={() => handleMouseOver(index + 1)}
/>
);
})}
</div>
<div id='message'></div>
<div>
<input
type='text'
placeholder='Your Name'
required
value={review.Name}
onChange={(e) => setReview({ ...review, Name: e.target.value })}
className='wpcf7-form-control'
/>
</div>
<div>
<input
type='text'
placeholder='Review Title'
required
value={review.Title}
onChange={(e) => setReview({ ...review, Title: e.target.value })}
className='wpcf7-form-control'
/>
</div>
<textarea
placeholder='Your comment'
required
value={review.Body}
onChange={(e) => setReview({ ...review, Body: e.target.value })}
className='wpcf7-form-control'
/>
<button type='submit' className='submit wpcf7-form-control wpcf7-submit' onClick={createReview}>
submit
</button>
</div>
</form>
</div>
<div className='themesflat-spacer clearfix' data-desktop={80} data-mobile={60} data-smobile={60} />
</div>
);
}
export default Ratings;

REACT JS FIREBASE FIRESTORE- how can i update my field in a document?

here is my manageexam.jsx file
this is where the update happen when i click the manage button on the table. i want to update a specific document id (3BelYq7lMxRNrWKknCRK- this is a sample of my document id but ofcourse there will be a lot of document id when i will add more inside the collection.) but i want to update the fields without manually adding the document Id that i want to update.
const ManageExam = () => {
const [description,setDesc]=useState("")
const [title,setTitle]=useState("")
function handleUpdate(e){
e.preventDefault();
const examcollref = doc(db,'Exams' "3BelYq7lMxRNrWKknCRK")
updateDoc(examcollref,{
title:title,
description:description
} ).then(response => {
alert("updated")
}).catch(error =>{
console.log(error.message)
})
}
return (
<div className="manageExam">
<Sidebar/>
<div className="manageExamContainer">
<div className="examInfo">
<h1>Manage Exam</h1>
</div>
<div className="left">
<div className="leftForm">
<div className="leftTitle">
Exam information
</div>
<br />
<div className="leftTitle">
</div>
<form onSubmit={handleUpdate}>
<label >Exam Title</label>
<input
type="text"
placeholder={title.doc}
value={title}
onChange={e => setTitle(e.target.value)}/>
<label htmlFor="">Description</label>
<textarea
id="desc"
cols="30"
rows="7"
value={description}
onChange={e =>setDesc(e.target.value)}
></textarea>
<button type="submit">Update</button>
</form>
</div>
</div>
<div className="right">
<div className="rightForm">
<div className="rightTitle">
Add Questions
<Link to= {`add_question`}style={{textDecoration:"none"}} className="link" >
Add new
</Link>
</div>
<div className="rightContainer">
{/* <p>1. What is the Meaning of db?</p> */}
{/* <div>
<input type="radio" name="option1" value="database" checked/>
<label htmlFor="">database</label>
</div>
<div>
<input type="radio" name="option2" value="data" disabled/>
<label htmlFor="">data</label>
</div>
<div>
<input type="radio" name="option3" value="databytes" disabled/>
<label htmlFor="">databytes</label>
</div>
<div>
<input type="radio" name="option4" value="databoard" disabled/>
<label htmlFor="">databoard</label>
</div>
<br />
<button>update</button>
<button>delete</button> */}
</div>
</div>
</div>
</div>
</div>
)
}
export default ManageExam
export const Examtable = ({id}) => {
const [list,setExamlist] = useState([])
// function to call the list from the firestore
useEffect (()=>{
const unsub = onSnapshot(
collection(db, "Exams"), //"exams -> pangalan ng database/("collection") ko"
(snapShot) => {
let list = [];
snapShot.docs.forEach((doc) => {
list.push({ id: doc.id, ...doc.data() });
});
setExamlist(list);
console.log(list.id);
},
(error) => {
console.log(error);
}
);
return () => {
unsub();
};
},[]);
const handleDelete = async (id) => {
alert("Do you want to delete?")
//window.confirm("Are you sure you want to delete?");
try {
await deleteDoc(doc(db, "Exams", id));
setExamlist(list.filter((item) => item.id !== id));
console.log(id)
} catch (err) {
console.log(err);
}
};
const actionColumn = [{field: "action", headerName: "Action", width: 200, renderCell:(params)=>{
return(
<div className="cellAction">
<div className="manageButton"> {/*/exam/manage_exam*/}
<Link to={`/exam/manage_exam/${params.row.id}`} style={{textDecoration:"none"}} className="link" >
Manage
</Link>
</div>
<div className="deleteButton" onClick={() => handleDelete(params.row.id)}>Delete</div>
</div>
)
}}];
return (
<div className="examtable" >
<div className="examtableTitle">
Exam
<Link to="/exam/new_exam/" style={{textDecoration:"none"}} className="link">
Add new
</Link>
</div>
<DataGrid
className="datagrid"
rows={list} //eto mga list nung nasa firebase
columns={examColumns.concat(actionColumn)}
pageSize={9}
rowsPerPageOptions={[9]}
checkboxSelection
/>
</div>
)
}
export default Examtable
here is the examtable.jsx where all the document in the collection will be displayed.
when i click the manage button, the url will display like this (localhost:3000/exam/manageexam/3BelYq7lMxRNrWKknCRK,, its because i click on this document but i cant update it at all because the console always said the id was undefined. i hope you understand what im saying
Because your pass id with Link in Examtable file.I think u must use useParams from react-router-dom in ur ManageExam.
First you need add id in your route path file, like this.
path: '/exam/manageexam/:id'
And then, in ur ManageExam.
import {useParams} from 'react-router-dom'
const ManageExam = () => {
const {id} = useParams()
const [description,setDesc]=useState("")
const [title,setTitle]=useState("")
function handleUpdate(e){
e.preventDefault();
const examcollref = doc(db,'Exams', id)
updateDoc(examcollref,{
title:title,
description:description
} ).then(response => {
alert("updated")
}).catch(error =>{
console.log(error.message)
})

react simple keyboard not able to type in multiple input

I have following code of Calculator.jsx where everything looks fine.The main thing I want to achieve is keyboard to displayed only on input click which is done but the keyboard does not seem to type though the following code looks fine. Are there any other way to show/hide keyboard only on input click as well as make keyboard be able to type. My code for Calculator.jsx is
Calculator.jsx
import React, { useState, useRef, useEffect } from 'react';
import './Calculator.css'
import { Link } from 'react-router-dom';
import Keyboard from "react-simple-keyboard";
import "react-simple-keyboard/build/css/index.css";
const Calculator = () => {
const [inputs, setInputs] = useState({});
const [layoutName, setLayoutName] = useState("default");
const [inputName, setInputName] = useState("default");
const keyboard = useRef();
const [keyboardVisibility, setKeyboardVisibility] = useState(false);
useEffect(() => {
function clickHanlder(e) {
if (
!(e.target.nodeName === "INPUT") &&
!e.target.classList.contains("hg-button") &&
!e.target.classList.contains("hg-row")
) {
setKeyboardVisibility(false);
}
}
window.addEventListener("click", clickHanlder);
return window.removeEventListener("click", clickHanlder, true);
}, []);
const onChangeAll = inputs => {
setInputs({ ...inputs });
console.log("Inputs changed", inputs);
};
const handleShift = () => {
const newLayoutName = layoutName === "default" ? "shift" : "default";
setLayoutName(newLayoutName);
};
const onKeyPress = button => {
console.log("Button pressed", button);
if (button === "{shift}" || button === "{lock}") handleShift();
};
const onChangeInput = event => {
const inputVal = event.target.value;
setInputs({
...inputs,
[inputName]: inputVal
});
keyboard.current.setInput(inputVal);
};
const getInputValue = inputName => {
return inputs[inputName] || "";
};
return (
<div>
<div className="bg">
<div className="deposit">
<div className="header">
<h1>Deposit Calculator</h1>
<div className="form">
<form className="calculator">
<div className="form-group">
<label for="depositAmount">Deposit Amount:</label>
<span className="rupees">Rs</span>
<input className="IInput"
type="text"
name='depositAmount'
placeholder='0'
value={getInputValue("depositAmount")}
onChange={onChangeInput}
onFocus={() => {
setKeyboardVisibility(true);
setInputName("depositAmount")
}}
/>
</div>
<div className="form-group">
<label for="interestRate">Interest Rate:</label>
<input className= "IIinput"
type="text"
name='Interest'
placeholder='0'
value={getInputValue("interestRate")}
onChange={onChangeInput}
onFocus={() => {
setKeyboardVisibility(true);
setInputName("interestRate")
}}
/>
<span className= "percent">%</span>
</div>
<div class="form-group">
<label for="Tenure">Tenure:</label>
<input className="Input"
type='number'
min='1'
max='5'
name='tenure'
placeholder='1 year'
value={getInputValue("tenure")}
onChange={onChangeInput}
onFocus={() => {
setKeyboardVisibility(true);
setInputName("tenure")
}}
/>
</div>
{ keyboardVisibility && (
<Keyboard
keyboardRef={(r) => (keyboard.current = r)}
layoutName={layoutName}
onChange={onChangeAll}
onKeyPress={onKeyPress}
/>
)}
</form>
<button className="calculate">Calculate
</button>
</div>
<div className="given">
<p >
Total Deposit: Rs 0
</p>
<p>
Interest: Rs 0
</p>
<p>
Maturity Amount: Rs 0
</p>
</div>
</div>
</div>
</div>
<Link to="/">
<button className="Back">
<i class="fas fa-angle-double-left"></i>
</button>
</Link>
</div>
);
};
export default Calculator;
You are setting the inputs state by spreading input string from keyboard onChangeAll into an object setInputs({ ...inputs }). If I enter ab it will set as {0: "a", 1:"b"}.
Update the onChange prop in Keyboard to onChangeAll and pass inputName prop with your inputName state value. Read react-simple-keyboard DOCS.
onChangeAll
const onChangeAll = (inputs) => {
console.log("Inputs changed", inputs);
setInputs(inputs);
};
Keyboard
{keyboardVisibility && (
<Keyboard
keyboardRef={(r) => (keyboard.current = r)}
layoutName={layoutName}
onChangeAll={onChangeAll}
onKeyPress={onKeyPress}
inputName={inputName}
/>
)}
CodeSandbox link

how to pass input data to another component in react

this is what i want to make
If I press the edit button on App.tsx,
I want to display the data in input text in AddToto.tsx.
I would appreciate it if you could tell me what method to use.
this is App.tsx
const App: React.FC = (props) => {
const [todos, setTodos] = useState<Todo[]>([]);
const [users, setUsers] = React.useState([] as Voca[]);
const editData = (id: number) => {
const item = users.find((user) => user.id === id);
console.log(item.word);
};
return (
<div className="App">
<h1>add word</h1>
<NewTodo onAddTodo={todoAddHandler} />
<hr />
<h1>edit word</h1>
<AddTodo />
<hr />
<table>
{users.map((user, index) => (
<tr key={index}>
<td>{user.word}</td>
<td>{user.meaning}</td>
<td>{user.enrollmentDate}</td>
<td>{user.editDate}</td>
<td className="opration">
<button onClick={() => removeData(user.id)}>delete</button>
</td>
<td>
<button
className="btn btn-warning"
onClick={() => {
editData(user.id);
}}
>
edit
</button>{" "}
</td>
</tr>
))}
</table>
</div>
);
};
export default App;
this is AddTodo.tsx
class AddTodo extends Component {
render() {
return (
<form>
<div className="form-control">
<label htmlFor="word">word:</label>
<input type="text" id="word" />
<br />
<label htmlFor="todo-meaning">meaning:</label>
<input type="text" id="todo-meaning" />
</div>
<button type="submit">save</button>
</form>
);
}
}
export default AddTodo;
In this case,
I don't know how to pass data to another component...
In editData, once you've found the item, set state which is passed as a prop to AddTodo:
const [userBeingEdited, setUserBeingEdited] = useState<Voca | null>(null);
const editData = (id: number) => {
setUserBeingEdited(users.find((user) => user.id === id));
};
return (
// ...
<AddTodo userBeingEdited={userBeingEdited} />
// AddTodo.tsx
export default ({
userBeingEdited,
}: {
userBeingEdited: Voca | null,
}) => (
<form>
<div className='form-control'>
<label htmlFor='word'>word:</label>
<input type='text' id='word' defaultValue={userBeingEdited?.word} />
<br />
<label htmlFor='todo-meaning'>meaning:</label>
<input type='text' id='todo-meaning' defaultValue={userBeingEdited?.meaning} />
</div>
<button type='submit'>save</button>
</form>
);

Resources