How can I delete an item from my todolist - javascript

I am trying to learn react js , but I don't know how to delete an item from my list, could you help me ? Actually, I am not professional , but I am really interested in learning, there is my codes which add some new item to my list properly, but I don't know how to delete them when I click on their checkbox/delete button.
import React, { useState } from "react";
const App = () => {
const [NewTaskText, setNewTaskText] = useState("");
const [Tasks, setTasks] = useState(["do a task", "samira"]);
const addTask = (e) => {
e.preventDefault();
if (!NewTaskText) return;
setTasks((currentTasks) => {
return [...currentTasks, NewTaskText];
});
setNewTaskText("");
};
const onchangeInput = (e) => {
const value = e.target.value;
setNewTaskText(value);
};
return (
<div className="row">
<form onSubmit={addTask}>
<div className="row col s6">
<div className="input-field col s10">
<textarea
id="textarea1"
className="materialize-textarea"
value={NewTaskText}
onChange={onchangeInput}
></textarea>
<label htmlFor="textarea1">What needs to be done ?</label>
</div>
</div>
<div className="row col s6">
<br></br>
<a className='waves-effect waves-light btn' href="/#" onClick={addTask}>
<i className='material-icons left' >
add_circle
</i>
Add
</a>
</div>
</form>
<div className="row">
<div className="row col s9">
<ul className="collection with-header">
<li className="collection-header">
<h4>Todo List</h4>
<form>
<div className="input-field">
<input id="search" type="search" required />
<label className="label-icon" htmlFor="search">
<i className="material-icons">search</i>Search
</label>
<i className="material-icons">close</i>
</div>
</form>
</li>
<label>
{Tasks.map((item, i) => {
return (
<li className="collection-item" key={i}>
<input type="checkbox" />
<span>
{item}
</span>
<span>
<a href="#!" className="secondary-content">
<i className="material-icons" >delete</i>
<i className="material-icons">check_circle</i>
</a>
</span>
</li>
);
})}
</label>
</ul>
</div>
</div>
</div>
);
};
export default App;

You can delete the item from the array by using index:
<i className="material-icons" onClick={() => handleDelete(i)}>delete</i>
and define your function above the return statement:
const handleDelete = i => {
const taskList = [...Tasks]
taskList.splice(i, 1)
setTasks(taskList)
}
Here it is important to know that you have to make a copy of the state if it is an object or an array. Because if you modify the original array or object, react won't register that as a change, and won't re-render. That is why I did const taskList = [...Tasks]. You can also use a library like lodash which provides some neat ways of handling objects and arrays

Just add a onClick handler to button which should delete item
<i className="material-icons" onClick={ () => {
setTasks((prevTasks) => {
const updatedPrevTasks = [...prevTasks];
updatedPrevTasks.splice(i, 1);
return updatedPrevTasks;
});
}}>delete</i>

Related

how do i map an array in react js i have tried but there is some problem can anyone help me

So I try to get data from localDataStorage and try to populate on screen in react but the react is showing error `[{',' expected" in place of '.' in jsx line localStorageData.iength or if i remove this from code than it's showing same error for 'localDataStorage.map' it asking me to remove '.'
import { useEffect, useState } from "react";
import "./inbox.css";
const Inbox = () => {
const [localStorageData, setlocalStorageData] = useState([])
useEffect =(()=>{
JSON.parse(localStorage.getItem('todos')).then(data=> setlocalStorageData(data))
}, [localStorageData])
return (
{localStorageData.length > 0 &&
localDataStorage.map((element, index) => (
<div className="inbox" key ={index}>
<div className="bullet">➣</div>
<div className="msg">{element.message}</div>
<div className="btn-container">
<div className="date">{element.title}</div>
<div className="edit btn hide">
<i className="fa-solid fa-pen-to-square"></i>
</div>
<div className="delete btn hide">
<i className="fa-solid fa-trash"></i>
</div>
</div>
</div>
))
}
)
}
export default Inbox;
the error is as following
[{
"resource": "/C:/Users/PC/Desktop/web/new/src/component/inbox/inbox.js",
"owner": "typescript",
"code": "1005",
"severity": 8,
"message": "',' expected.",
"source": "ts",
"startLineNumber": 14,
"startColumn": 22,
"endLineNumber": 14,
"endColumn": 23
}]
Remove the outer braces in your return statement. Braces like this are only used inside JSX.
Also, you probably meant .length instead of .iength.
import React from "react"
import { useEffect, useState } from "react"
import "./inbox.css"
const Inbox = () => {
const [localStorageData, setlocalStorageData] = useState([])
useEffect =
(() => {
JSON.parse(localStorage.getItem("todos"))
.then(data => setlocalStorageData(data))
.catch(err => console.log(err))
},
[localStorageData])
return (
<>
{localStorageData.length > 0 &&
localStorageData.map((element, index) => (
<div className="inbox" key={index}>
<div className="bullet">➣</div>
<div className="msg">{element.message}</div>
<div className="btn-container">
<div className="date">{element.title}</div>
<div className="edit btn hide">
<i className="fa-solid fa-pen-to-square"></i>
</div>
<div className="delete btn hide">
<i className="fa-solid fa-trash"></i>
</div>
</div>
</div>
))}
</>
)
}
export default Inbox
you are not wrapping code into single element
try
return (
<>
{
localStorageData.length > 0 &&
localData.map((element, index) => (
<div className="inbox" key={index}>
<div className="bullet">➣</div>
<div className="msg">{element.message}</div>
<div className="btn-container">
<div className="date">{element.title}</div>
<div className="edit btn hide">
<i className="fa-solid fa-pen-to-square"></i>
</div>
<div className="delete btn hide">
<i className="fa-solid fa-trash"></i>
</div>
</div>
</div>
))
}
</>
)
i believe there should be localStorageData.map and not localData.map

How to increase a usestate number inside a div in React.js

I have a useState inside div, I want to update the counter beacuse I want to get another img url from exArr array. is there a way to update counter inside a div?
let exArr = [];
const [counter, setCounter] = useState(0);
return (
<div className="menRight">
{
products.filter(product => product.productGender.includes('Kids')).slice(0, showProducts).map(product => (
<div className="menRightCard">
<Link to={`/productBuy?id=${product.productImageFolder}`}>
<div className="menRightCardimg">
<i className="far fa-heart"></i>
<img src={exArr[counter]} alt="" />
/* I WANT TO CHANGE HERE */ { setCounter(counter => counter + 1) }
</div>
<div className="menRightCardInfo">
<p className="productInfo">
{product.productName}
</p>
<p className="productPrice">
€{product.productPrice}
</p>
</div>
</Link>
</div>
))
}
<div className="loadMore">
<button onClick={showMoreItems}>Load More Products</button>
</div>
</div>
);
}

How can I prevent TypeError: Cannot read property 'map' of undefined when submitting empty form data?

Ok so my code works great but when I hit submit while the input field is empty my .map method doesnt have a input value to add to the end of the API string to search for so I get a typeError: cannot read property of map undefined. because input is my state and if I dont enter a string into the input field the state doesnt get updated so the .map method has no updated state to go off of.
SO how would I set the input field to require text to be entered before the submit button will even call the function "SearchApi"?
I was trying to set conditionals but it didnt seem to work....like....if input.length < 1 { setInput("E.T") just so it has something to search for and doesn't return an error. I also was looking online at react form validation tutorials but I feel like maybe i'm going about this all wrong. Any help would be appriciated thank you!
import React, {useState, useEffect} from 'react';
const SearchBar = () => {
const [search, setSearch] = useState([]);
const [input, setInput] = useState('');
const [trending, setTrending] = useState([]);
const [upcoming, setUpcoming] = useState([]);
// Input Field
const onUserInput = ({target}) => {
setInput(target.value);
}
// Api Call
const SearchApi = (event) => {
const aUrl = "https://api.themoviedb.org/3/search/movie?api_key=fde5ddeba3b7dec3fc1f51852ca0fb95";
const newUrl = aUrl +'&query=' + input;
event.preventDefault();
fetch(newUrl)
.then((response) => response.json())
.then((data) => {
setSearch(data.results);
})
.catch((error) => {
console.log('Error!! Data interupted!:', error)
})
}
return (
// Heading
<div>
<div className="container">
<h1>Movie Search Extravaganza!</h1>
{/* Input Field and Button Form */}
<form>
<input value={input} onChange={onUserInput} type="text" className="searchbar" aria-label="searchbar" placeholder="search" name="movie" required/>
<br></br>
<button type="submit" onClick={SearchApi} aria-label="searchbutton" className="searchBtn">Movie Express Search</button>
</form>
</div>
<div className="byName-container">
<h1 className="row-label" tabIndex="0">Movies Related To Your Search</h1>
<ul className="flexed-search">
{search.map((item) =>
<div className="poster-container">
<li className="list-item" key={item.id}>
<img className="image-element" tabIndex="0" alt="movie poster" aria-label={item.title} src={`https://image.tmdb.org/t/p/w500${item.poster_path}`} />
<h3 className="posterTitle">{item.title}</h3>
</li>
</div>
)}
</ul>
</div>
<div className="trending-container">
<h1 className="row-label" tabIndex="0">This Weeks Trending Tittles</h1>
<ul className="flexed-trending">
{trending.map((it) =>
<div className="poster-container">
<li className="list-item" key={it.id}> <img className="image-element" tabIndex="0" aria-label={it.title} alt="movie poster" src={`https://image.tmdb.org/t/p/w500${it.poster_path}`} />
<h3 className="posterTitle">{it.title}</h3>
</li>
</div>
)}
</ul>
</div>
<div className="upcoming-container">
<h1 className="row-label" tabIndex="0">Upcomming Movies</h1>
<ul className="flexed-upcoming">
{upcoming.map((inn) =>
<div className="poster-container">
<li className="list-item" key={inn.id}>
<img className="image-element" tabIndex="0" alt="movie poster" aria-label={inn.title} title={`${inn.title}: ==> ${inn.overview}`} src={`https://image.tmdb.org/t/p/w500${inn.poster_path}`} />
<h3 className="posterTitle">{inn.title}</h3>
</li>
</div>
)}
</ul>
</div>
</div>
)
};
export default SearchBar;```
You made a small mistake in your form
Change this :
<form>
...
<button type="submit" onClick={SearchApi} aria-label="searchbutton" className="searchBtn">
Movie Express Search
</button>
</form>
By :
<form onSubmit={SearchApi}>
...
<button type="submit" aria-label="searchbutton" className="searchBtn">
Movie Express Search
</button>
</form>
The "required" of the input will work. Demo: Stackblitz
PS : Check the keys in all your map functions
{search.map(item => (
<div className="poster-container"> //pass the key here and do the same for others
<li className="list-item" key={item.id}>
you could try to make required explicit with
required={true}

React/Redux, Redux store changes but does not immediately render items without leaving the page and returning

When I clicked on the button "Buy", the store redux is updated and
push a new array to the initial state. But I don't see any new render
in the shop-cart section without leaving the page and go in again so I
can see new items. I'm new to React and Redux, I have been trying to fix it but it was not working and i'm very confused about it
Here is the reducer section
const initialState = {
counter : 0,
cartData : [
{
id : 1,
name : "Melon",
price : 100,
img : "https://d1hr6nb56yyl1.cloudfront.net/product-images/93368-280.jpg",
quantity : 1
},
{
id : 1,
name : "Melon",
price : 100,
img : "https://d1hr6nb56yyl1.cloudfront.net/product-images/93368-280.jpg",
quantity : 1
},
]
};
function cartNumber(state = initialState, action) {
console.log(state.cartData)
let cartIndex = [...state.cartData];
switch(action.type){
case "INCREMENT" :
return {
...state,
cartData : cartIndex.concat(action.newData)
};
break;
case "DECREMENT" :
default :
return state;
}
return cartIndex
}
export default cartNumber;
Here is the Item Detail page and Items Cart section
import React, {useEffect,useState} from "react";
import SubCart from "../components/SubCart";
import { useSelector, useDispatch } from "react-redux";
import {Link} from "react-router-dom";
function ItemDetail({match, history}){
const dispatch = useDispatch();
const [item, setItem] = useState({});
const scroll = () => {window.scroll(0,0)};
useEffect(() => {
const fetchItem = async () => {
const fetchItem = await fetch(
`https://5e5a9fc26a71ea0014e61f04.mockapi.io/api/${match.params.category}/${match.params.id}`
);
const item = await fetchItem.json();
setItem(item);
};
fetchItem();
scroll();
}, [])
const showRating = (rating) => {
var result = [];
for(var i = 1; i <= rating; i++){
result.push(<i className="fa fa-star" key={i + 1} style={{fontSize : ".8rem", color : "#ff4e00", padding : "0rem .1rem"}}></i>);
}
for (var j = 1; j <= (5-rating); j++) {
result.push(<i className="far fa-star" key={i + 1} style={{fontSize : ".8rem", padding : "0rem .1rem"}}></i>);
}
return result;
}
const backButton = () => {
history.goBack();
}
const showSubcart = () => {
let sub = document.getElementById("subcart-section");
let bg = document.getElementById("bg-ccc");
sub.classList.toggle("showSubCart");
bg.classList.toggle("bg-ccc");
dispatch({type : "INCREMENT", newData : item });
}
return (
<div style={{backgroundColor: "white"}}>
<div className="item-detail" style={{paddingBottom : "1rem"}}>
<div className="section-heading">
<div className="section-content">
<div className="icon-home">
<i className="fas fa-home"></i>
</div>
<div className="nav-home">
<Link to="/">Home</Link>
</div>
<div className="icon-to">
<i className="fas fa-chevron-right"></i>
</div>
<div className="nav-cart">
<Link to="/">{item.category}</Link>
</div>
</div>
</div>
<div className="img-detail">
<img src={item.img} alt={item.name} />
<span className="icon-section"><i className="far fa-heart"></i></span>
<span className="icon-section-arrow" onClick={() => backButton()}><i className="fas fa-arrow-left"></i></span>
</div>
<div className="item-detail-content">
<div className="container">
<Link to="/" style={{color : "black"}}><span className="category">{item.category}</span></Link>
<div><h2>{item.name}</h2></div>
<div><h3>{item.price}$</h3></div>
<div>
<ul>
<li>{showRating(item.rating)} <span style={{fontSize : ".8rem"}}>(210)</span></li>
</ul>
</div>
<div className="buy" onClick={() => showSubcart()}>
<span className="buy-text">Buy</span>
<span className="buy-icon"><i className="fas fa-shopping-cart"></i></span>
</div>
<div className="description">
<div className="head-description">
<h3><i className="far fa-bookmark"></i> Description</h3>
</div>
<div className="body-description">
<p>...</p>
</div>
</div>
<div className="infoPolicy mt-top">
<div className="box-head">
<i className="fas fa-truck"></i>
</div>
<div className="box-content">
<p className="note-p">FREE NATIONAL DELIVERY</p><span className="note">(Products over 50$)</span>
</div>
</div>
<div className="infoPolicy mt-top">
<div className="box-head">
<i className="fas fa-sync-alt"></i>
</div>
<div className="box-content">
<p className="note-p">Returns are Easy</p><span className="note">(Return 30days for items)</span>
</div>
</div>
<div className="infoPolicy mt-top mt-bt">
<div className="box-head">
<i className="fas fa-headset"></i>
</div>
<div className="box-content">
<p className="note-p">Telephone consultation</p><span className="note">(Free from 8:00 - 21:00 every day)</span>
</div>
</div>
</div>
</div>
<SubCart />
</div>
</div>
);
}
export default ItemDetail;
import React, {useState} from "react";
import {Link} from "react-router-dom";
import {useSelector} from "react-redux";
function ItemCart(){
let data = useSelector(state => state.cartData);
let [items, setItem] = useState(data);
return (
<div className="subcart-link">
{items.map((item, index) => (
<div className="d-flex" key={index}>
<div className="subcart-img">
<img src={item.img} alt="pubg"/>
</div>
<div className="subcart-item-content">
<Link to="/">{item.name}</Link>
<div className="subcart-item-detail">
<p>{item.price}$<span className="subcart-quantity">x 2</span></p>
</div>
</div>
<div className="delete-click">
<p>x</p>
</div>
</div>
))}
</div>
);
}
at your ItemCart you are duplicating redux state into a react state, which is not advisable. they are two different entities, though you can have both types at your application a given specific state should be handled by a specific state manager.
at your ItemCart remove useState altogether, and map over data variable instead. your issue comes from the fact that your items state inherits only the original redux state, but since they are different states, it doesnt get updated when redux state changes.
fwiw, dont use dom manipulation to handle classes like you do at showSubCart, this is not good. I suggest to use some boolean logic instead to toggle class, based on some props or state value.

React Error: Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null

EDIT: [SOLVED by the community - in the answers!] Thanks everyone
I'm trying to add search functionalities to my webApp (a list of the movies I own). To do this, from the app I'm calling a functional component (MovieListFiltered) which has the following code:
MovieListFiltered.js:
import React from 'react'
const MovieListFiltered = (props) => {
const newData = props.moviesAfterFilter
if(newData !== null) {
const newMovies = newData.map((movie, i) =>
{
return(
<div className="col s12 m3 l3" key={i} movieid ={movie.idFromTmdb}>
<div className="card">
<div className="card-image waves-effect waves-block waves-light">
<img src={movie.url2poster} alt={movie.movieTitle} className="responsive-img" />
<p className="littleFont" align="center"><span><b>{movie.movieTitle}</b></span></p>
</div>
<div className="card-action">
<a href="#" onClick={() => this.props.viewMovieInfo(movie.idFromTmdb)}>Movie Details</a>
</div>
</div>
</div>
);
})
console.log(newMovies)
props.movieCallback(newData, newMovies);
} else {
return null
}
}
export default MovieListFiltered
So, basically, notything special there: you see many console.log calls, that was just to make sure the correct array of data was passed (and it is!)
In App.js:
... code not interesting goes here ...
callbackFromList = (childDataData, childDataMovies) => {
this.setState({moviesToFilter: childDataData});
this.setState({moviesToShow: childDataMovies});
this.setState({totalResults: childDataData.length});
}
render()
{
... some not interesting code goes here...
return(
<div className="App">
<Nav />
<div>
<div className="container">
<div className="row">
<div className="col s10 offset-s1">
<MovieListFiltered viewMovieInfo={this.viewMovieInfo} movieCallback={() => this.callbackFromList} ref={this.movieListRef} moviesAfterFilter={this.state.moviesFiltered}></MovieListFiltered>
</div>
</div>
</div>
</div>
</div>
);
}
Can you please help me? I've read all the questions already made here on stackoverflow, but nothing seems to fit to my case.
I think you are wanting something like this:
const MovieListFiltered = (props) => {
const newData = props.moviesAfterFilter
if(newData !== null) {
const newMovies = newData.map((movie, i) => (
<div className="col s12 m3 l3" key={i} movieid ={movie.idFromTmdb}>
<div className="card">
<div className="card-image waves-effect waves-block waves-light">
<img src={movie.url2poster} alt={movie.movieTitle}
className="responsive-img" />
<p className="littleFont" align="center"><span><b>
{movie.movieTitle}</b></span></p>
</div>
<div className="card-action">
<a href="#" onClick={() =>
this.props.viewMovieInfo(movie.idFromTmdb)}>Movie Details</a>
</div>
</div>
</div>
);
)
console.log(newMovies)
props.movieCallback(newData, newMovies)
return newMovies
} else {
return null
}
}
Here a cleaner version with only one return. That may not be what you're looking for though.
import React from 'react'
const MovieListFiltered = (props) => {
const newData = props.moviesAfterFilter || []; // add 'or' if null or undefined
const newMovies = newData.map((movie, i) => (
<div className="col s12 m3 l3" key={i} movieid ={movie.idFromTmdb}>
<div className="card">
<div className="card-image waves-effect waves-block waves-light">
<img src={movie.url2poster} alt={movie.movieTitle} className="responsive-img" />
<p className="littleFont" align="center"><span><b>{movie.movieTitle}</b></span></p>
</div>
<div className="card-action">
<a href="#" onClick={() => this.props.viewMovieInfo(movie.idFromTmdb)}>Movie Details</a>
</div>
</div>
</div>
));
console.log(newMovies)
props.movieCallback(newData, newMovies);
return newMovies;
}
export default MovieListFiltered
You are only returning a value from the else block. The if block is not currently returning anything. You probably want to make the last line of the if block return newMovies;
import React from 'react'
const MovieListFiltered = (props) => {
const newData = props.moviesAfterFilter
if(newData !== null) {
const newMovies = newData.map((movie, i) =>
{
return(
<div className="col s12 m3 l3" key={i} movieid ={movie.idFromTmdb}>
<div className="card">
<div className="card-image waves-effect waves-block waves-light">
<img src={movie.url2poster} alt={movie.movieTitle} className="responsive-img" />
<p className="littleFont" align="center"><span><b>{movie.movieTitle}</b></span></p>
</div>
<div className="card-action">
<a href="#" onClick={() => this.props.viewMovieInfo(movie.idFromTmdb)}>Movie Details</a>
</div>
</div>
</div>
);
});
console.log(newMovies);
props.movieCallback(newData, newMovies);
return newMovies;
}
return null;
}
export default MovieListFiltered
Also, you might notice I got rid of the entire else block - this is because it's not necessary if you return from the corresponding if block.

Categories