I am new to React and I am trying to filter a list of emails in .users-list. I just want to return what the user is typing on the SearchBox but it does not work. Any suggestions?
Dashboard.js
import React, { Component } from "react";
import Button from "../Button/Button";
import SearchBox from "../SearchBox/SearchBox";
import "./Dashboard.css";
import fire from "../../fire"
class Dashboard extends Component {
constructor(){
super();
this.state = {
users:[],
searchField:''
}
}
handleLogout = () => {
fire.auth().signOut();
};
render() {
const {users, searchField} = this.state
const filteredUsers = users.filter(users => (users.users.toLowerCase.inc))
return (
<div>
<h2>Welcome</h2>
<button onClick={this.handleLogout}>Logout</button>
<div className="users-container">
<div>
<SearchBox
placeholder="Enter email..."
handleChange={(e) =>
this.setState({ searchField: e.target.value})
}
/>
</div>
<ul className="users-list">
<li>
<span>jean#gmail.com</span>
</li>
<li>
<span>albert#gmail.com</span>
</li>
<li>
<span>kevin#gmail.com</span>
</li>
<li>
<span>lucie#gmail.com</span>
</li>
</ul>
</div>
</div>
);
}
}
export default Dashboard;
SearchBox.js
import React from 'react';
const SearchBox = (props) => {
return(
<input
type='search'
className='search'
placeholder={props.placeholder}
onChange={props.handleChange}
/>
)
}
export default SearchBox
You can follow: codesandbox DEMO
For optimize performance:
useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render.
import React, { useMemo, useState } from "react";
import "./styles.css";
const usersData = [
{id:1,email: 'jean#gmail.com'},
{id:2,email: 'albert#gmail.com'},
{id:3,email: 'kevin#gmail.com'},
]
export default function App() {
const [search, setSearch] = useState("");
const filteredUsers = useMemo(() => {
if (search) {
return usersData.filter(
(item) =>
item.email
.toLowerCase()
.indexOf(search.toLocaleLowerCase()) > -1
);
}
return usersData;
}, [search]);
return (
<div className="App">
<h1>users list</h1>
<input type="search" name="search" value={search} onChange={e => setSearch(e.target.value)} />
<ul>
{filteredUsers.length > 0 ?
(filteredUsers && filteredUsers.map(item => (
<li key={item.id}>{item.email}</li>
))): <div>empty</div>
}
</ul>
</div>
);
}
Related
Here how i can change this code to functional component. If i try to change this to functional component in console data is keep on printing. how i can solve that error. Kindly provide solution for this.
import React, { Component } from "react";
import { connect } from "react-redux";
import { getUsers } from "../actions/exampleAction";
function Users (props) {
props.getUsers();
const { users } = props.users;
console.log(props.users);
return (
<div>
{users.length &&
users.map((user) => {
return (
<React.Fragment key={user.id}>
<h6> {user.first_name} </h6>
<p> {user.last_name} </p>
<p> {user.email}</p>
<p>
<img key={user.avatar} src={user.avatar} alt="avatar" />
</p>
</React.Fragment>
);
})}
</div>
);
}
const mapStateToProps = (state) => ({ users: state.users });
export default connect(mapStateToProps, { getUsers })(Users);
Since, at the during the initial rendering of the component, props.getUsers() is called, when it is changed, again the props changes and component is rendered.
That's why you get multiple console logs.
You can read about side effects and using hooks on Functional Components here.
import React, { useEffect } from "react";
import { connect } from "react-redux";
import { getUsers } from "../actions/exampleAction";
function Users(props) {
const { users } = props.users;
useEffect(() => {
props.getUsers();
}, []);
return (
<div>
{users.length &&
users.map((user) => {
return (
<React.Fragment key={user.id}>
<h6> {user.first_name} </h6>
<p> {user.last_name} </p>
<p> {user.email}</p>
<p>
<img key={user.avatar} src={user.avatar} alt="avatar" />
</p>
</React.Fragment>
);
})}
</div>
);
}
const mapStateToProps = (state) => ({ users: state.users });
export default connect(mapStateToProps, { getUsers })(Users);
You can also use hook available from "react-redux" instead of mapStateToProps or mapDispatchToProps as given below
And you don't need to pass getUsers as props because you already import it at the top so you can directly use it without props.
So go through following code and improve your coding standard
import React, { useEffect } from "react";
import {useSelector} from 'react-redux'
import { getUsers } from "../actions/exampleAction";
function Users(props) {
const users = useSelector(state => state.users);
useEffect(() => {
getUsers();
}, []);
if(!users.length) return null;
const userData = users.map((user) => {
return (
<React.Fragment key={user.id}>
<h6> {user.first_name} </h6>
<p> {user.last_name} </p>
<p> {user.email}</p>
<p>
<img key={user.avatar} src={user.avatar} alt="avatar" />
</p>
</React.Fragment>
);
});
return (
<div>
{userData}
</div>
);
}
export default Users;
Issue:
within my child component:
TypeError: items.map is not a function
I don't understand why not, I saw that others had this issue when they were mapping through something that wasn't an array. However mine clearly is. As seen on the fourth line in the parent component.
Parent comp:
import React, {useState} from 'react';
import ListItem from '../components/listItem';
const Pagethree = () => {
const[items,setItem] = useState([]);
return(
<div>
<CreateItem items={items} setItem={setItem}/>
<ListItem items={items}/>
</div>
)
};
export default Pagethree;
Child comp 1:
import React, {useState} from "react";
const ListItem = (props) =>{
const {items} = props;
return(
<div>
<h1>list item comp</h1>
<ul>
{
items.map((item, i) =>
<div class="flex">
<input type="checkbox" />
{item}
<button>delete</button>
</div>
)
}
</ul>
</div>
)
};
export default ListItem;
child component 2:
import React from "react";
const CreateItem = (props) =>{
const {items, setItem} = props;
const addItem = (e) =>{
e.preventDefault();
setItem([...items, items]);
setItem("");
console.log(items);
}
return(
<div>
<h1>create item comp</h1>
<form onsubmit={addItem}>
<input type="text" value={items} onChange={e => setItem(e.target.value)}/>
<button type="submit">add item</button>
</form>
</div>
)
};
export default CreateItem;
It's not entirely clear what your goal is, but this may help. It's a basic form that adds individual items (on submit) to an items list.
const { useState } = React;
const App = () => {
const [items, setItems] = useState([]);
const handleSubmit = (e) => {
e.preventDefault();
const item = e.target.elements['itemInput'].value;
setItems([...items, item]);
e.target.reset();
}
const itemsDisplay = `Your items are: ${items.join(', ')}`;
return (
<React.Fragment>
<p>{itemsDisplay}</p>
<form onSubmit={handleSubmit}>
<input name='itemInput' />
<button type='submit'>Add Item</button>
</form>
</React.Fragment>
);
}
ReactDOM.render(<App />, document.body);
<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>
When you call setItem on input change (in CreateItem) you’re setting the state on the parent component to a single (non-array) value. The subsequent render throws because items is no longer an array.
I'm making a To Do List app using React, I made 2 components which is the App component and the ToDoItem component, In the App component I have 2 states one of them is being used to add tasks and the second is to set the items array, In the ToDoItem component I have a state that is being used to mark items (Setting its text decoration to line through).
I'm also using UUID to make a uniqe key to each one of the components,
The problem is that everytime I try to remove an item from the list, it doesn't working and its also changes the uuids
App component:
import React, {useState} from "react";
import ToDoItem from "./ToDoItem";
import { v4 as uuidv4 } from 'uuid';
function App() {
const [item, setItem] = useState("");
const [items, setItems] = useState([]);
function handleChange(event){
const newItem = event.target.value;
setItem(newItem);
}
function addItem(){
if(item.length > 0){
console.log(item + " inserted!");
setItems( (prevItems) =>{
return[...prevItems, item];
});
setItem("");
}
}
function deleteItem(id){
setItems((prevItems) =>{
return prevItems.filter(
(key) => {
return key !== id;
}
)
});
}
return (
<div className="container">
<div className="heading">
<h1>To-Do List</h1>
</div>
<div className="form">
<input type="text" onChange={handleChange} value={item}/>
<button onClick={addItem}>
<span>Add</span>
</button>
</div>
<div>
<ul>
{ items.map((todoItem) => (
<ToDoItem
key={uuidv4()}
id={uuidv4()} //Must be used in order to be able to use it or deleting an item
item={todoItem}
onDelete={deleteItem}
/>
))}
</ul>
</div>
</div>
);
}
export default App;
ToDoItem component:
import React, {useState} from "react";
import { BiTrash } from "react-icons/bi";
function ToDoItem(props){
const [isChecked, setChecked] = useState(false);
function markItem(){
setChecked(prevValue => {
return !prevValue;
});
}
return(
<li ><span onClick={markItem} style={{textDecoration: isChecked ? "line-through" : "none"}}>
{props.item}</span> {isChecked ?
<span className="trash" onClick={() => {
props.onDelete(props.id);
}}>
<BiTrash/></span> : null}</li>
);
}
export default ToDoItem;
On every App render you make a function call (uuid()) which results in new keys (unmount) and new id, you should move the id prop to your todoItem state on creation:
// on creating a todo item
const todoItem = { id: uuid() }
I have a movie app which displays a card for each movie in a state.
I would like to use a dynamic search bar to render movies corresponding to the search input value.
For instance, if I start to write "Har", I want to see only movies with a title that begins with "Har".
The app code :
import React, { useState, useEffect } from "react";
import "./App.css";
import Logo from "../components/Logo";
import Search from "../components/Search";
import Add_movie_button from "../components/Add_movie_button";
import Random_movie_button from "../components/Random_movie_button";
import Movie_card from "../components/Movie_card";
import axios from "axios";
const BASE_URL = "https://api.themoviedb.org/3/movie/";
const API_KEY = "4bcd155b9b8734cb8559319cdbfaf62f";
function App() {
const [movieinfos, setMovieinfos] = useState([]);
console.log(movieinfos);
useEffect(() => {
axios
.get("http://localhost:5000")
.then(function (response) {
const movies = response.data.movies;
console.log(response.data.movies);
return Promise.all(
movies.map((movie) =>
axios.get(
`${BASE_URL}${movie.movieid}?api_key=${API_KEY}&language=fr`
)
)
);
})
.then((responses) => {
console.log(responses);
setMovieinfos(
responses.map((response) => ({
Genres: response.data.genres,
Overview: response.data.overview,
Poster: response.data.poster_path,
Company: response.data.production_companies,
Release: response.data.release_date,
Title: response.data.title,
Id: response.data.id,
}))
);
});
}, []);
return (
<div className="App">
<div className="Header">
<Logo />
</div>
<div className="Menu">
<Search movieinfos={movieinfos} setMovieinfos={setMovieinfos} />
<Add_movie_button />
<Random_movie_button data={movieinfos} />
</div>
<div className="Movies">
{movieinfos.map((movie) => (
<Movie_card key={movie.Title} data={movie} />
))}
</div>
</div>
);
}
export default App;
The search bar code :
import React from "react";
import "./style.css";
const Search = (props) => {
console.log(props);
return (
<div className="Search">
<input
type="search"
id="Search_input"
placeholder="Rechercher un film ..."
value= //WHAT DO I NEED TO WRITE HERE ?
onChange={(event) =>
/*WHAT DO I NEED TO WRITE HERE ?*/ event.target.value
}
/>
</div>
);
};
export default Search;
You could create a state variable
[searchWord, setSearchWord] = useState('')
your input would then contain
value={searchWord}
onChange={e => setSearchWord(e.target.value)}
You could then filter your array movieinfos with the searchWord and map the returning array to display only the movies with the search world
movieinfos.filter(movie => movie.title.includes(searchWord)).map(movie => return <Movie_card key={movie.Title} data={movie} />)
I have json data file. I want to make a search with the names of the data and display the typed names when I click the search button.
I get the value of input in the console when I type something however I am not able to display it on the screen
How can I display the value of this input ?
my code is below
PostResults.jsx
import React from "react";
const PostResults = (props) => {
const {name} = props.posts
return(
<div className="">
<p className="titles">{name}</p>
</div>
)
}
export default PostResults
Posts.jsx
import React, { useState, useEffect } from "react";
import PostResults from './PostResults'
const Posts = (props) => {
const [posts, setPosts] = useState([]);
const [searchTerm,setSearchTerm]=useState([]);
const getData = () => {
fetch('data.json')
.then(response => {
return response.json()
//console.log(response)
})
.then(data => {
setPosts(data)
console.log(data)
})
}
useEffect(() => {
getData()
},[])
const submitHandler = (event) => {
event.preventDefault()
{searchTerm ? searchTerm : console.log("none")}
}
return(
<div className="">
<input
type="text"
placeholder="Search Anything"
name="query"
onChange={e => setSearchTerm(e.target.value)}
className="search-input"
/>
<button
onClick={submitHandler}
type="submit"
className="search-button"
>
<i className="fas fa-search"></i>
</button>
{posts.map(posts => (
<PostResults key={posts.id} posts={posts}/>
))}
</div>
)
}
export default Posts
App.jsx
import React from "react";
import "./style.css";
import 'bootstrap/dist/css/bootstrap.min.css'
import Posts from './components/Posts'
export default function App() {
return (
<div className="container">
<div className="row">
< Posts />
</div>
</div>
);
}