This question already has answers here:
Curly Brackets in Arrow Functions
(3 answers)
Closed 1 year ago.
I am new at React and I am trying to do a very simple Todo app but I already got stuck.
I initialized with create-react-app and somehow nothing is showing when I loop through the state and call a component passing data to it.
Here is the App.js:
import React, { useState } from 'react';
import Todo from './components/Todo';
function App() {
const [title, setTitle] = useState(['test1', 'test2', 'test3'])
return (
<div className="App">
{title.map(item => {
<div>
<Todo item={item} />
</div>
})}
</div>
);
}
export default App;
And this is the Todo.js:
import React from 'react';
const Todo = ({item}) => {
return <div>{item}</div>
}
export default Todo;
The Todo component is called from the right folder (I checked many times), the files are saved and React is not returning any error, it just displays nothing in the DOM. If I loop through the title and display its content from the app.js it displays everything as normal.
Also, a console.log from inside Todo component is not triggered meaning, somehow the component is not imported.
What am I doing wrong here?
It's not displaying because you are not returning anything from map
Try something like below:-
Return from map using return keyword
{title.map(item => {
return (
<div>
<div>{item}</div>
</div>
)
})}
OR implicitly return line below:-
{title.map(item => (
<div>
<div>{item}</div>
</div>
))}
try something like this:
import React, { useState } from 'react';
import Todo from './components/Todo';
function App() {
const [title, setTitle] = useState(['test1', 'test2', 'test3'])
return (
<div className="App">
{title.map(item => {
return(
<div>
<Todo item={item} />
</div>
);
})}
</div>
);
}
export default App;
or
import React, { useState } from 'react';
import Todo from './components/Todo';
function App() {
const [title, setTitle] = useState(['test1', 'test2', 'test3'])
return (
<div className="App">
{title.map(item =>(
<div>
<Todo item={item} />
</div>
))}
</div>
);
}
export default App;
Related
Hi do you render a react elements from an array of strings using object literal to get its value? let say for example I got an array of strings and I want to mapped on it using a function that returns an object literal with predefined values, if the strings matched return the react element. Here's what i've tried but doesn't display the icons
import { useCallback, useEffect, useMemo } from "react";
import PersonIcon from "#mui/icons-material/Person"
import ShoppingCartIcon from '#mui/icons-material/ShoppingCart'
import SecurityIcon from '#mui/icons-material/Security'
import LocalActivityIcon from '#mui/icons-material/LocalActivity'
export default function App() {
const iconNames = useMemo(()=>['PersonIcon','ShoppingCartIcon', 'SecurityIcon', 'LocalActivityIcon'],[]);
const getIcons = (icon) =>{
const icons = {
PersonIcon: <PersonIcon />,
ShoppingCartIcon: <ShoppingCartIcon />,
SecurityIcon: <SecurityIcon />,
LocalActivityIcon: <LocalActivityIcon />
}
return icons[icon];
}
const displayIcons = useCallback((arr) => {
return <ul>{arr.map((icon) => { return getIcons[icon] })}</ul>
},[])
useEffect(()=>{
displayIcons(iconNames)
})
return (
<div className="App">
<h1>Icons</h1>
{displayIcons}
</div>
);
}
Assuming that the icons are imported and static, perhaps the icons object could be defined outside of the component, so that even without useMemo or useCallback, it would not be re-created when the component re-renders.
The getIcons might not be necessary to access the icons in the object, as in the output JSX, the icons[name] can be wrapped in a curly braces {} to render the icon.
Example (live demo on: stackblitz):
import PersonIcon from '#mui/icons-material/Person';
import ShoppingCartIcon from '#mui/icons-material/ShoppingCart';
import SecurityIcon from '#mui/icons-material/Security';
import LocalActivityIcon from '#mui/icons-material/LocalActivity';
// π Can be defined here if the icons are imported and static
const icons = {
PersonIcon: <PersonIcon />,
ShoppingCartIcon: <ShoppingCartIcon />,
SecurityIcon: <SecurityIcon />,
LocalActivityIcon: <LocalActivityIcon />,
};
// π Just an array of the icon names for testing
const iconNames = Object.keys(icons);
export default function App() {
return (
<div className="App">
<h1>Icons</h1>
<ul>
{iconNames.map((name, index) => (
<li key={index}>{icons[name]}</li>
))}
</ul>
</div>
);
}
However depending on the use case, perhaps also consider to use other approaches instead of accessing it from an object to display a list of icons.
The example below displays a list of icons, and could also pass the MUI props to style it if needed (may not work for other libraries).
Example (live demo on: stackblitz):
// Works for MUI icons but might not for other libraries
const icons = [PersonIcon, ShoppingCartIcon, SecurityIcon, LocalActivityIcon];
export default function App() {
return (
<div className="App">
<h1>Icons</h1>
<ul>
{icons.map((Icon, index) => (
<li key={index}>
<Icon fontSize="large" color="primary" />
</li>
))}
</ul>
</div>
);
}
Just another possible approach that also works (with MUI) and accepts props for the icons, by defining the icon as component inside map:
Example (live demo on: stackblitz):
// Works for MUI icons but might not for other libraries
const icons = { PersonIcon, ShoppingCartIcon, SecurityIcon, LocalActivityIcon };
const iconNames = Object.keys(icons);
export default function App() {
return (
<div className="App">
<h1>Icons</h1>
<ul>
{iconNames.map((icon, index) => {
const Icon = icons[icon];
return (
<li key={index}>
<Icon fontSize="large" color="primary" />
</li>
);
})}
</ul>
</div>
);
}
You are calling displayIcons as a variable while this is a function.
getIcons is a function not an array. You should do getIcons(icon)
Your code can be reduce to this
import { useCallback, useEffect, useMemo } from "react";
import PersonIcon from "#mui/icons-material/Person"
import ShoppingCartIcon from '#mui/icons-material/ShoppingCart'
import SecurityIcon from '#mui/icons-material/Security'
import LocalActivityIcon from '#mui/icons-material/LocalActivity'
export default function App() {
const iconNames = ['PersonIcon','ShoppingCartIcon', 'SecurityIcon', 'LocalActivityIcon']
const getIcons = (icon) => {
const icons = {
PersonIcon: <PersonIcon />,
ShoppingCartIcon: <ShoppingCartIcon />,
SecurityIcon: <SecurityIcon />,
LocalActivityIcon: <LocalActivityIcon />
}
return icons[icon];
}
const displayIcons = useCallback(() => {
return (
<ul>{iconNames.map((icon) => { return getIcons(icon) })}</ul>
)
},[iconNames])
return (
<div className="App">
<h1>Icons</h1>
{displayIcons()}
</div>
);
}
In my App.js component I have this state :
const [searchText, setSearchText] = useState('');
I have passed this into the Search component as a prop to update the text that I write in the search bar that I have created in the search component.
This is the error that is coming : bundle.js:461 Uncaught TypeError: props.handleSearchNote is not a function
Here is how i have passed in the function in App.js:
And this is my search component:
import React from 'react'
import { MdSearch } from 'react-icons/md'
const Search = (props) => {
return (
<div className='search'>
<MdSearch className='search-icons' size='1.3em' />
<input
onChange={(event) =>
props.handleSearchNote(event.target.value)
}
type='text'
placeholder='type to search...'
/>
</div>
);
};
export default Search;
This is where I have passed the Search component in App.js
return (
<>
<div className='container'>
<Search handlSearchNote={setSearchText} />
{console.log(searchText)}
<NotesList
notes={notes.filter((note) => note.text.toLowerCase().includes(searchText))}
handleAddNote={addNote}
handleDeleteNote={deleted} />
</div>
</>
);
}
export default App;
You're assigning setSearchText to handlSearchNote not handleSearchNote. You forgot the 'e' in handle. This happens to me all the timeπ
.
I'm new to React. I'm trying to add additional functionality of deleting the record from the list by setting the value.
here is my App.js
import React, { useState } from "react";
import data from "./data";
import List from "./List";
function App() {
const [movies, setMovie] = useState(data);
return (
<main>
<section className='container'>
<h3>{movies.length} Movies to Watch</h3>
<List movies={movies} setMovie />
<button onClick={() => setMovie([])}>clear all</button>
</section>
</main>
);
}
export default App;
In List.js, Im trying to delete the record when clicking on Watched button. Can I call setMovie inside the List component? is it a correct way?
List.js
import React from "react";
const List = ({ movies }, setMovie) => {
return (
<>
{movies.map((movie) => {
const { id, name, year, image } = movie;
return (
<article key={id} className='person'>
<img src={image} alt={name} />
<div>
<h4>{name}</h4>
<button
className='btn'
onClick={(id) =>
setMovie(movies.filter((movie) => movie.id !== id))
}
>
watched
</button>
<p>{year}</p>
</div>
</article>
);
})}
</>
);
};
export default List;
You have two mistakes in your code. First:
<List movies={movies} setMovie />
This shorthand assigns a value of true to setMovie. To assign the setMovie function to it, you must instead do:
<List movies={movies} setMovie={setMovie} />
And secondly this:
const List = ({ movies }, setMovie) => {
Should be this:
const List = ({ movies, setMovie }) => {
try:
<List movies={movies} setMovie={setMovie} />
this way the funcition will appear in the List component as a prop.
The way you were doing, it will just appear as true
I'm making a simple react app to take trivia questions and answers from an api and display them as a game.
My development of this app has been running smoothly and updating as per expected, however when I imported a decode function to make the trivia questions present correctly, I noticed that further edits of the code would result in a blank white screen, after commenting out some code I've managed to isolate what code seems to be causing the issue.
App.js
import React from 'react'
import Questions from './Questions'
import { nanoid } from 'nanoid'
import { decode } from 'he'
function App() {
const [tempState, setTempState] = React.useState(false)
const [data, setData] = React.useState({})
React.useEffect(() => {
fetch("https://opentdb.com/api.php?amount=5&category=9&difficulty=medium")
.then(res => res.json())
.then(info => setData(info.results.map(item => {
return {
type: item.type,
question: item.question,
correct_answer: item.correct_answer,
incorrect_answers: item.incorrect_answers,
id: nanoid()
}})))
}, [])
const questionElements = data.map(item => (
<Questions
key={item.id}
type={item.type}
question={item.question}
correct_answer={item.correct_answer}
incorrect_answers={item.incorrect_answers}
/>
))
return (
<main>
<img className="blob--top"
src={require('./blobs.png')}
/>
<img className="blob--bottom"
src={require('./blobs1.png')}
/>
{tempState ?
<div className="quiz--container">
<div>
{questionElements}
</div>
</div> :
<>
<div className="title--container">
<div className="title--init">
<h2 className="title--header">Quizzical</h2>
<h4 className="title--subheader">A battle of the brains</h4>
<button className="game--start"
onClick={() => setTempState(!tempState)}
>
Start quiz</button>
</div>
</div>
</>
}
</main>
);
}
export default App;
Questions.js
import React from 'react'
import { decode } from 'he'
export default function Questions(props) {
return(
<div className="question--container">
<h4>{decode(props.question)}</h4>
<div className="question--items">
<button>{decode(props.correct_answer)}</button>
<button>{decode(props.incorrect_answers[0])}</button>
<button>{decode(props.incorrect_answers[1])}</button>
<button>{decode(props.incorrect_answers[2])}</button>
</div>
</div>
)
}
commenting out the following two code sections in App.js resolves the error
const questionElements = data.map(item => (
<Questions
key={item.id}
type={item.type}
question={item.question}
correct_answer={item.correct_answer}
incorrect_answers={item.incorrect_answers}
/>
))
<div>
{questionElements}
</div>
any ideas on what I'm doing wrong? no error messages show up in react, it just shows a blank white screen.
The blank white screen is caused by the error data.map is not a function, which is caused by your setting default value of the data state to be an empty object while it should be an empty array (so that you can map through).
To fix this error, simply set the default value of data to be an empty array.
const [data, setData] = React.useState([])
Code Sandbox: https://codesandbox.io/embed/inspiring-rhodes-gp5kki?fontsize=14&hidenavigation=1&theme=dark
so I've recently completed a project that I was working on that displayed a list of pokemon, and once clicked on, the user is directed to the pokemon information page.
It looks as follows:
So I have my main dashboard.js that contains my "PokemonList" as follows:
import React, { Component } from "react";
import styled from "styled-components";
import PokemonList from "../pokemon/PokemonList";
export default class Dashboard extends Component {
render() {
return (
<div>
<div className="row">
<div className="col">
<PokemonList />
</div>
</div>
</div>
);
}
}
my PokemonList.js is responsible for obtaining the Pokemon information from the PokeAPI and the code is as follows:
import React, { Component } from "react";
import PokemonCard from "./PokemonCard";
import axios from "axios";
export default class PokemonList extends Component {
state = {
url: "http://pokeapi.co/api/v2/pokemon/?limit=600",
pokemon: null
};
async componentDidMount() {
const res = await axios.get(this.state.url);
this.setState({ pokemon: res.data["results"] });
}
render() {
return (
<React.Fragment>
{this.state.pokemon ? (
<div className="row">
{this.state.pokemon.map(pokemon => (
<PokemonCard
key={pokemon.name}
name={pokemon.name}
url={pokemon.url}
/>
))}
</div>
) : (
<h1>Loading Pokemon</h1>
)}
</React.Fragment>
);
}
}
The pokemonList is built of several pokemonCards that's then displayed, but I don't think the coding for that is needed for what I'm looking for.
If I wanted to enable pagination, would I have to incorporate the code within my Dashboard.js or the pokemonList.js?
-----------------------EDIT--------------------------------------
What you could use is this library: https://www.npmjs.com/package/react-js-pagination
Then in your code the pagination would be smth like this:
<Pagination
activePage={this.state.activePage}
itemsCountPerPage={this.state.itemsCountPerPage}
totalItemsCount={this.state.pokemon.length}
pageRangeDisplayed={5}
onChange={::this.handlePageChange.bind(this)}
/>
handlePageChange function:
handlePageChange(pageNumber) {
this.setState({activePage: pageNumber});
}
then in the render function of your pokemonList.js:
let indexOfLastTodo = this.state.activePage * this.state.itemsCountPerPage;
let indexOfFirstTodo = indexOfLastTodo - this.state.itemsCountPerPage;
let renderedPokemons = this.state.pokemon.slice(indexOfFirstTodo, indexOfLastTodo);
and finally
{renderedPokemons.map(pokemon => (
<PokemonCard
key={pokemon.name}
name={pokemon.name}
url={pokemon.url}
/>
))}
Of course don't forget to include activePage and itemsCountPerPage in your state. I think I have done something like this in one of my earlier projects. Enjoy!