Trying to change React Style attribute by changing state hook - reactjs

Transform is not updating the style component below. I have console logged the state to ensure that it is changing and it was, just not the style component (it kept the color red).
import React, {useState} from 'react';
const Carousel = () => {
let [selectedIndex, setSelectedIndex] = useState(0)
const [cellCount,] = useState(9);
let [transform, setTransform] = useState({color: 'red'});
const prevButton = () => {
setSelectedIndex(selectedIndex-1);
setTransform({color: 'green !important'})
console.log(selectedIndex)
console.log(transform)
};
const nextButton = () => {
setSelectedIndex(selectedIndex+1);
setTransform({color: 'red !important'})
console.log(transform)
}
return (
<>
<div className="scene">
<div style={transform} className="carousel">
<div className="carousel__cell">1</div>
<div className="carousel__cell">2</div>
<div className="carousel__cell">3</div>
<div className="carousel__cell">4</div>
<div className="carousel__cell">5</div>
<div className="carousel__cell">6</div>
<div className="carousel__cell">7</div>
<div className="carousel__cell">8</div>
<div className="carousel__cell">9</div>
</div>
</div>
<button onClick={prevButton}>
Previous
</button>
<button onClick={nextButton}>
Next
</button>
</>
)
}

React inline style doesn't know the !important property. There is usually always a way to avoid using it, and it is better to do so.
If you just don't avoid using !important, it will work here.
If you have to set it, this would work:
import React, { useState } from 'react';
const Carousel = () => {
let [selectedIndex, setSelectedIndex] = useState(0);
let [transform, setTransform] = useState({ color: 'red' });
const prevButton = () => {
setSelectedIndex(selectedIndex - 1);
setTransform({ ...{ color: 'green' } });
// rotateCarousel();
console.log(selectedIndex);
console.log(transform);
};
const nextButton = () => {
setSelectedIndex(selectedIndex + 1);
setTransform({ ...{ color: 'red' } });
console.log(transform);
// rotateCarousel();
};
return (
<>
<div className="scene">
<div
ref={el => {
if (el) {
el.style.setProperty('color', transform.color, 'important');
}
}}
className="carousel"
>
<div className="carousel__cell">1</div>
{transform.color}
<div className="carousel__cell">2</div>
<div className="carousel__cell">3</div>
<div className="carousel__cell">4</div>
<div className="carousel__cell">5</div>
<div className="carousel__cell">6</div>
<div className="carousel__cell">7</div>
<div className="carousel__cell">8</div>
<div className="carousel__cell">9</div>
</div>
</div>
<button onClick={prevButton}>Previous</button>
<button onClick={nextButton}>Next</button>
{transform.color}
</>
);
};
export default Carousel;

Related

How can we create a editable `<code>` tag on fly and add different attributes to that

On click on Code button, how can we create a editable <code> tag on fly and add different attributes in react web app ?
Or may be an editable field display as code tag ? Could someone please advise here ?
import React, { useState } from 'react';
import { useNavigate } from "react-router-dom";
const Admin = () => {
const [createCode, setCreateCode] = useState("");
const navigate = useNavigate();
const createCodeSection = () => {
const newElement = React.createElement('code', {key: 'ele'+ new Date().getTime(), className:'codehighlight'}, `--sample code to enter-- `,);
setCreateCode(createCode => [...createCode, newElement]);
}
const handleLogout = () => {
localStorage.removeItem('loginEmail');
navigate("/login");
};
return (
<div id="App">
<div className='adminSection'>
<div className='row'>
<div className="logout">
<img src="/images/logout.png" alt="Logout" onClick={handleLogout}></img>
</div>
<div className='createBlogSection'>
<div className='row'>
<button onClick={createCodeSection}>Code</button>
<button>Image</button>
<button>Code</button>
</div> <br></br>
<textarea>
{createCode}
</textarea>
</div>
</div>
</div>
</div>
)
}
export default Admin;
css:
.codehighlight{
background-color: #353232;
color: #fff;
}

Use State not updating as expected

Fairly new to react and trying to build a clone of The Movie Database site. I want this toggle switch to change my api call from movies to tv. It starts working after a couple clicks, but then it throws everything off and it's not displaying the correct items anyway. Not really sure what's going on here...or even why it starts working after two clicks. Anyone know whats up with this?
import React, { useState, useEffect } from "react";
import axios from "axios";
import API_KEY from "../../config";
const Popular = ({ imageUri }) => {
// GET POPULAR MOVIES
const [popularMovies, setPopularMovies] = useState("");
const [genre, setGenre] = useState("movie");
console.log(genre);
const getPopular = async () => {
const response = await axios.get(
`https://api.themoviedb.org/3/discover/${genre}?sort_by=popularity.desc&api_key=${API_KEY}`
);
setPopularMovies(response.data.results);
};
useEffect(() => {
getPopular();
}, []);
const listOptions = document.querySelectorAll(".switch--option");
const background = document.querySelector(".background");
const changeOption = (el) => {
let getGenre = el.target.dataset.genre;
setGenre(getGenre);
getPopular();
listOptions.forEach((option) => {
option.classList.remove("selected");
});
el = el.target.parentElement.parentElement;
let getStartingLeft = Math.floor(
listOptions[0].getBoundingClientRect().left
);
let getLeft = Math.floor(el.getBoundingClientRect().left);
let getWidth = Math.floor(el.getBoundingClientRect().width);
let leftPos = getLeft - getStartingLeft;
background.setAttribute(
"style",
`left: ${leftPos}px; width: ${getWidth}px`
);
el.classList.add("selected");
};
return (
<section className="container movie-list">
<div className="flex">
<div className="movie-list__header">
<h3>What's Popular</h3>
</div>
<div className="switch flex">
<div className="switch--option selected">
<h3>
<a
data-genre="movie"
onClick={(e) => changeOption(e)}
className="switch--anchor"
>
In Theaters
</a>
</h3>
<div className="background"></div>
</div>
<div className="switch--option">
<h3>
<a
data-genre="tv"
onClick={(e) => changeOption(e)}
className="switch--anchor"
>
On TV
</a>
</h3>
</div>
</div>
</div>
<div className="scroller">
<div className="flex flex--justify-center">
<div className="flex flex--nowrap container u-overScroll">
{popularMovies &&
popularMovies.map((movie, idX) => (
<div key={idX} className="card">
<div className="image">
<img src={imageUri + "w500" + movie.poster_path} />
</div>
<p>{movie.title}</p>
</div>
))}
</div>
</div>
</div>
</section>
);
};
export default Popular;
You're using the array index as your key prop when you're mapping your array.
You should use an id that is specific to the data that you're rendering.
React uses the key prop to know which items have changed since the last render.
In your case you should use the movie id in your key prop instead of the array index.
popularMovies.map((movie) => (
<div key={movie.id} className="card">
<div className="image">
<img src={imageUri + 'w500' + movie.poster_path} />
</div>
<p>{movie.title}</p>
</div>
));
Also
You're calling the api directly after setGenre. However state changes aren't immediate. So when you're making your api call you're still sending the last movie genre.
Two ways of fixing this:
You could call your function with the genre directly, and change your function so it handles this case:
getPopular('movie');
Or you could not call the function at all and add genre as a dependency of your useEffect. That way the useEffect will run each time the genre change.
useEffect(() => {
getPopular();
}, [genre]);
PS: You should consider splitting your code into more component and not interacting with the DOM directly.
To give you an idea of what it could look like, I refactored a bit, but more improvements could be made:
const Popular = ({ imageUri }) => {
const [popularMovies, setPopularMovies] = useState('');
const [genre, setGenre] = useState('movie');
const getPopular = async (movieGenre) => {
const response = await axios.get(
`https://api.themoviedb.org/3/discover/${movieGenre}?sort_by=popularity.desc&api_key=${API_KEY}`
);
setPopularMovies(response.data.results);
};
useEffect(() => {
getPopular();
}, [genre]);
const changeHandler = (el) => {
let getGenre = el.target.dataset.genre;
setGenre(getGenre);
};
const isMovieSelected = genre === 'movie';
const isTvSelected = genre === 'tv';
return (
<section className="container movie-list">
<div className="flex">
<MovieHeader>What's Popular</MovieHeader>
<div className="switch flex">
<Toggle onChange={changeHandler} selected={isMovieSelected}>
In Theaters
</Toggle>
<Toggle onChange={changeHandler} selected={isTvSelected}>
On TV
</Toggle>
</div>
</div>
<div className="scroller">
<div className="flex flex--justify-center">
<div className="flex flex--nowrap container u-overScroll">
{popularMovies.map((movie) => {
const { title, id, poster_path } = movie;
return (
<MovieItem
title={title}
imageUri={imageUri}
key={id}
poster_path={poster_path}
/>
);
})}
</div>
</div>
</div>
</section>
);
};
export default Popular;
const Toggle = (props) => {
const { children, onChange, selected } = props;
const className = selected ? 'switch--option selected' : 'switch--option';
return (
<div className={className}>
<h3>
<a
data-genre="movie"
onClick={onChange}
className="switch--anchor"
>
{children}
</a>
</h3>
<div className="background"></div>
</div>
);
};
const MovieHeader = (props) => {
const { children } = props;
return (
<div className="movie-list__header">
<h3>{children}</h3>
</div>
);
};
const MovieItem = (props) => {
const { title, imageUri, poster_path } = props;
return (
<div key={idX} className="card">
<div className="image">
<img src={imageUri + 'w500' + poster_path} />
</div>
<p>{title}</p>
</div>
);
};

React question : how to pass an id from a component to another on click?

I need your help with an app that I am building. It has a forum page and I have some issues with the forum and post components.
I am trying to pass the id of the post that the user clicked on, with history.push so on the post page the id in the url that I try to get with useParams, has the value of the one I send with history.push. The purpose is for some queries I do so I show the post with its comments.
For now the layout isn’t great because I have to make this feature work.
I do not understand why it doesn’t. My console.logs show null or undefined which make no sense to me.
Thank you if you can help me with this.
Here you have two routes present in the App component. It is important for the last route, the Post one were I use :id so I can get it with useParams.
{/* Route for Trainings Wakeup Rebirth */}
<Route path='#forum' exact component={TrainingsWakeupRebirth} />
<Route path='#forum/:id' exact component={Post} />
Here you have the entire code of the Forum page. Like that you can see how I use history.push to send the value.id of the post to the Post component and the way the component itself is built.
import React, { useState, useEffect, useRef } from 'react';
import { useHistory } from 'react-router-dom';
import ReactPaginate from "react-paginate";
import Post from "../Post/Post";
import './TrainingsWakeupRebirth.scss';
import axios from "axios";
const TrainingsWakeupRebirth = (props) => {
let history = useHistory();
// const forumSectionRef = useRef();
// const postSectionRef = useRef();
const forumSection = document.getElementById('forum-block-wrapper');
const postSection = document.getElementById('post-section');
const showPost = () => {
if (forumSection.style.display === 'block') {
return forumSection.style.display = 'none',
postSection.style.display = 'block';
} else {
return forumSection.style.display = 'block',
postSection.style.display = 'none';
}
}
const [listOfPosts, setListsOfPosts] = useState([]);
const [pageNumber, setPageNumber] = useState(0);
const postsPerPage = 2;
const pagesVisited = pageNumber * postsPerPage;
const displayPosts = listOfPosts.slice(pagesVisited, pagesVisited + postsPerPage).map((value, key) => {
const forParams = () => {
return history.push(`#forum/${value.id}`);
}
const executeAll = () => {
forParams();
showPost();
if(forParams()) {
let id = value.id;
return id;
}
}
return (
<div key={key}>
<div className="topic-row" onClick={() => {executeAll()}}>
<div className="topic-title">{value.title}</div>
<div className="topic-image">
<img src={value.image} alt=""></img>
</div>
<div className="topic-message">{value.postText}</div>
</div>
</div>
);
});
const pageCount = Math.ceil(listOfPosts.length / postsPerPage);
const changePage = ({selected}) => {
setPageNumber(selected);
};
useEffect(() => {
axios.get("http://localhost:3001/posts").then((response) => {
setListsOfPosts(response.data);
});
}, []);
console.log(listOfPosts);
return (
<div className="forum" id="forum">
<div className="forum-section-wrapper page" id="forum-wrapper">
<div className="fluid-grid">
<div className="row">
<div className="col-12">
<div className="title">
<h1><span className="first-title-part">Krishna</span><span className="second-title-part">Hara</span></h1>
</div>
<div className="quote">
<span className="quote-left">FORUM</span><span className="quote-right">Eco Village</span>
</div>
</div>
</div>
<div className="row">
<div className="col-12">
<div className="forum-block-wrapper" id="forum-block-wrapper">
{displayPosts}
<ReactPaginate
previousLabel={"Previous"}
nextLabel={"Next"}
pageCount={pageCount}
onPageChange={changePage}
containerClassName={"paginationBttns"}
previousLinkClassName={"previousBttn"}
nextLinkClassName={"nextBttn"}
activeClassName={"paginationActive"}
/>
</div>
</div>
</div>
</div>
</div>
<div className="post-section" id="post-section">
<div className="fluid-grid">
<div className="row">
<div className="col-12">
<Post />
</div>
</div>
</div>
</div>
</div>
)
};
export default TrainingsWakeupRebirth;
Here is some code from the Post component, so you can see the code that should work but doesn't. Also the console.log(id)
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import axios from "axios";
const Post = (props) => {
let { id } = useParams();
const [postObject, setPostObject] = useState({});
const [comments, setComments] = useState([]);
const [newComment, setNewComment] = useState("");
console.log(id);
useEffect(() => {
axios.get(`http://localhost:3001/posts/byId/${id}`).then((response) => {
console.log(response);
setPostObject(response.data);
});
axios.get(`http://localhost:3001/comments/${id}`).then((response) => {
setComments(response.data);
});
}, [id]);
const addComment = () => {
axios.post("http://localhost:3001/comments", {
commentBody: newComment,
Postid: id,
})
.then((response) => {
const commentToAdd = { commentBody: newComment };
setComments([...comments, commentToAdd]);
setNewComment("");
});
};
console.log(postObject);
return (
<div className="post-section-wrapper">
{/* <div>
<div className="title">
{postObject.title}
</div>
<div className="image">
<img src={postObject.image}></img>
</div>
<div className="message">
{postObject.postText}
</div>
</div> */}
<div className="comments-wrapper">
<div className="">
<input
type="text"
placeholder="Comment..."
autoComplete="off"
value={newComment}
onChange={(event) => {
setNewComment(event.target.value);
}}
/>
<button onClick={addComment}> Add Comment</button>
</div>
<div className="comments-row">
{comments.map((comment) =>
(
<div key={comment.id} className="comment">
{comment.commentBody}
</div>
)
)}
</div>
</div>
</div>
);
}
export default Post;
Thank you very very much!!!
#DrewReese and #JoelHager Thank you so much for checking my code and for your advice. In the meantime I found out that we can pass to a component, aside from the pathname, other values with history.push that we retrieve by using useLocation in the component that we want to. I will answer my own question and add the code.
Here is my Forum component, I prefer adding the entire code so everything is clear. In forParams you will see how I pass the value that I need with useHistory and the attribute state and detail.
import React, { useState, useEffect, useRef } from 'react';
import { useHistory } from 'react-router-dom';
import ReactPaginate from 'react-paginate';
import Post from '../Post/Post';
import './TrainingsWakeupRebirth.scss';
import axios from 'axios';
const TrainingsWakeupRebirth = (props) => {
let history = useHistory();
// const forumSectionRef = useRef();
// const postSectionRef = useRef();
const forumSection = document.getElementById('forum-block-wrapper');
const postSection = document.getElementById('post-section');
const showPost = () => {
if (forumSection.style.display === 'block') {
return forumSection.style.display = 'none',
postSection.style.display = 'block';
} else {
return forumSection.style.display = 'block',
postSection.style.display = 'none';
}
}
const [listOfPosts, setListsOfPosts] = useState([]);
const [pageNumber, setPageNumber] = useState(0);
const postsPerPage = 2;
const pagesVisited = pageNumber * postsPerPage;
const displayPosts = listOfPosts.slice(pagesVisited, pagesVisited + postsPerPage).map((value, key) => {
const forParams = () => {
history.push(
{
pathname: `#forum#${value.id}`,
state: { detail: value.id }
}
);
}
const executeAll = () => {
forParams();
showPost();
}
return (
<div key={key} onClick={() => {executeAll()}}>
<div className="topic-row">
<div className="topic-title">{value.title}</div>
<div className="topic-image">
<img src={value.image} alt=""></img>
</div>
<div className="topic-message">{value.postText}</div>
</div>
</div>
);
});
const pageCount = Math.ceil(listOfPosts.length / postsPerPage);
const changePage = ({selected}) => {
setPageNumber(selected);
};
useEffect(() => {
axios.get("http://localhost:3001/posts").then((response) => {
setListsOfPosts(response.data);
});
}, []);
console.log(listOfPosts);
return (
<div className="forum" id="forum">
<div className="forum-section-wrapper page" id="forum-wrapper">
<div className="fluid-grid">
<div className="row">
<div className="col-12">
<div className="title">
<h1><span className="first-title-part">Krishna</span><span className="second-title-part">Hara</span></h1>
</div>
<div className="quote">
<span className="quote-left">FORUM</span><span className="quote-right">Eco Village</span>
</div>
</div>
</div>
<div className="row">
<div className="col-12">
<div className="forum-block-wrapper" id="forum-block-wrapper">
{displayPosts}
<ReactPaginate
previousLabel={"Previous"}
nextLabel={"Next"}
pageCount={pageCount}
onPageChange={changePage}
containerClassName={"paginationBttns"}
previousLinkClassName={"previousBttn"}
nextLinkClassName={"nextBttn"}
activeClassName={"paginationActive"}
/>
</div>
</div>
</div>
</div>
</div>
<div className="post-section" id="post-section">
<div className="fluid-grid">
<div className="row">
<div className="col-12">
<Post />
</div>
</div>
</div>
</div>
</div>
)
};
export default TrainingsWakeupRebirth;
In the Post component with useLocation and useEffect I get location.state.detail which is the id of the Post, that with useState I set to the constant postId.
import React, { useEffect, useState } from "react";
import { useParams, useHistory, useLocation } from "react-router-dom";
import axios from "axios";
import './Post.scss';
const Post = (props) => {
// let { id } = useParams();
const location = useLocation();
const [postId, setPostId] = useState();
useEffect(() => {
console.log(location.pathname); // result: '#id'
if(location.state) {
console.log(location.state.detail); // result: postId
setPostId(location.state.detail);
}
}, [location]);
const [postObject, setPostObject] = useState({});
const [comments, setComments] = useState([]);
const [newComment, setNewComment] = useState("");
// console.log(id);
useEffect(() => {
axios.get(`http://localhost:3001/posts/byId/${postId}`).then((response) => {
console.log(response.data);
setPostObject(response.data);
});
axios.get(`http://localhost:3001/comments/${postId}`).then((response) => {
setComments(response.data);
});
}, [postId]);
const addComment = () => {
axios.post("http://localhost:3001/comments", {
commentBody: newComment,
Postid: postId,
})
.then((response) => {
const commentToAdd = { commentBody: newComment };
setComments([...comments, commentToAdd]);
setNewComment("");
});
};
if(postObject !== null) {
console.log(postObject);
}
return (
<div className="post-section-wrapper">
{postObject !== null
?
<div className="posts-wrapper">
<div className="title">
{postObject.title}
</div>
<div className="image">
<img src={postObject.image}></img>
</div>
<div className="message">
{postObject.postText}
</div>
</div>
:
null
}
<div className="comments-wrapper">
<div className="">
<input
type="text"
placeholder="Comment..."
autoComplete="off"
value={newComment}
onChange={(event) => {
setNewComment(event.target.value);
}}
/>
<button onClick={addComment}> Add Comment</button>
</div>
<div className="comments-row">
{comments.map((comment) =>
(
<div key={comment.id} className="comment">
{comment.commentBody}
</div>
)
)}
</div>
</div>
</div>
);
}
export default Post;

Update className with UseEffect hook

Currently i am practising my React skills. Now i am working on my Hooks knowledge. I have used a Coctail API to load some data. Just for fun i divided this up into three categories with a navigation bar.
When i click on the navigation items i go to the subcategories. But my classes won't update so the tab system doesn't work. You guys know what i have to do here? I tried this in a few different ways but none worked.
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const OverView = () => {
const [ term, setTerm ] = useState('Gin');
const [ categorie, setCategorie ] = useState('Cocktail');
const [ debouncedTerm, setDebouncedTerm ] = useState(term);
const [ results, setResults] = useState([]);
useEffect(() => {
const timerId = setTimeout(() => {
setDebouncedTerm(term);
}, 10);
return () =>{
clearTimeout(timerId);
};
}, [term]);
useEffect(() => {
const search = async () => {
const { data } = await axios({
'method':'GET',
'url':'https://the-cocktail-db.p.rapidapi.com/filter.php',
'headers':{
'content-type':'application/octet-stream',
'x-rapidapi-host':'the-cocktail-db.p.rapidapi.com',
'x-rapidapi-key':'49adf3a5ccmsh5d525b0005370d3p1b460bjsn7b0add17579e',
'useQueryString':true
},'params':{
'i': debouncedTerm
},
});
setResults(data.drinks);
};
search();
}, [debouncedTerm]);
const renderResults = results.map((result) => {
return (
<div key={result.idDrink} className="four wide column" style={{marginBottom:"20px"}}>
<a href={result.idDrink}>
<div className="card">
<img src={result.strDrinkThumb} width="250"/>
<div className="header">{result.strDrink}</div>
</div>
</a>
</div>
);
});
return (
<div className="ui grid">
<div className="row">
<h3>Select your favourate drink to get started</h3>
<div className="ui top attached tabular menu">
<div
className={'item active'}
onClick={(e) => setTerm('Gin') }>
Gin
</div>
<div
className={'item'}
onClick={(e) => setTerm('Vodka')}>
Vodka
</div>
<div
className={'item'}
onClick={(e) => setTerm('Whiskey')}>
Whiskey
</div>
</div>
</div>
<div className="row">
{renderResults}
</div>
</div>
);
};
export default OverView;
Thanks in advance.My first problem is that i don't know how to add an extra action upon my hook. I can't attach an extra onClick event and don't know how to add this to my useEfect functions.
Set the className based on the term state atom, simple as that.
I also refactored things a bit:
the result component is now, well, a separate component
searching is refactored into a separate function
import React, { useState, useEffect } from "react";
import axios from "axios";
const ResultCard = ({ result }) => (
<div className="four wide column" style={{ marginBottom: "20px" }}>
<a href={result.idDrink}>
<div className="card">
<img src={result.strDrinkThumb} width="250" />
<div className="header">{result.strDrink}</div>
</div>
</a>
</div>
);
async function doSearch(term) {
const { data } = await axios({
method: "GET",
url: "https://the-cocktail-db.p.rapidapi.com/filter.php",
headers: {
"content-type": "application/octet-stream",
"x-rapidapi-host": "the-cocktail-db.p.rapidapi.com",
"x-rapidapi-key": "49adf3a5ccmsh5d525b0005370d3p1b460bjsn7b0add17579e",
useQueryString: true,
},
params: {
i: term,
},
});
return data;
}
const OverView = () => {
const terms = ["Gin", "Vodka", "Whiskey"];
const [term, setTerm] = useState("Gin");
const [results, setResults] = useState([]);
useEffect(() => {
doSearch(term).then((data) => setResults(data.drinks));
}, [term]);
return (
<div className="ui grid">
<div className="row">
<h3>Select your favourate drink to get started</h3>
<div className="ui top attached tabular menu">
{terms.map((t) => (
<div
className={["item", term === t ? "active" : null].filter(Boolean).join(" ")}
onClick={(e) => setTerm(t)}
>
{t}
</div>
))}
</div>
</div>
<div className="row">
{results.map((result) => (
<ResultCard result={result} key={result.idDrink} />
))}
</div>
</div>
);
};
export default OverView;
You may want to look into the classnames module; the arcane [].filter().join() expression would become cx({item: true, active: t === term}) :)

Building Dropdown component

I'm having a problem building a dropdown component. In the function to get the selected item I'm having this error :
Too many re-renders. React limits the number of renders to prevent an
infinite loop.
The code for the component :
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import '../../../App.css'
function Dropdown({ items }) {
//const [list, setList] = useState(items);
const [selectedItem, setSelectedItem] = useState(items[0]);
const [showItems, setShowItem] = useState(false);
const [setExpand, setExpandState] = useState("");
function toggleDropdown() {
setExpandState(setExpand === "" ? "dropdown-expanded dropdown-expanded-down" : "");
setShowItem(showItems === false ? true : false);
};
const Changed = (item) => {
setShowItem(false);
setSelectedItem(item);
}
return (
<div data-dropdown="" className={`dropdown-container dropdown ${setExpand}`} onClick={toggleDropdown} >
<div className="dropdown-display">
<div className="dropdown-display-content" >
<span data-expression="" class="OSFillParent"> {selectedItem.value} </span>
</div>
</div>
<div className="dropdown-list" style={{ display: showItems ? 'block' : 'none' }} >
<div className="scrollable-list scrollable-list-with-scroll">
{items.map(item =>
<div className="dropdown-popup-row" key={item.id} onClick={Changed(item)} > {item.value} </div>
)}
</div>
</div>
</div>
);
}
Dropdown.propTypes = {
items: PropTypes.array,
}
export default Dropdown;
The problem is on here onClick={Changed(item)}
You are calling this on each render, and it's modifying the state every render, so it gets called again recursively.
You can solve it by doing:
<div className="dropdown-popup-row"
key={item.id}
onClick={() => Changed(item)}>
{item.value}
</div>

Resources