How to make sure that only the secret text is displayed on click, in the panel of which the "show" button was clicked. Now two panels are revealed at once ...
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [visible, setVisible] = useState(true);
const onHandleVisible = () => {
setVisible(!visible);
};
return (
<div className="App">
<div className="panel">
<h3>Panel1</h3>
<button onClick={onHandleVisible}>Show</button>
{!visible ? (
<div>
<h1>I am secret text</h1>
</div>
) : null}
</div>
<div className="panel">
<h3>Panel2</h3>
<button onClick={onHandleVisible}>Show</button>
{!visible ? (
<div>
<h1>I am secret text 2</h1>
</div>
) : null}
</div>
</div>
);
}
https://codesandbox.io/s/frosty-nash-nx4v6
make 2 states
const [visible1, setVisible1] = useState(true);
const [visible2, setVisible2] = useState(true);
return (
<div className="App">
<div className="panel">
<h3>Panel1</h3>
<button onClick={() => setVisible1(!visible1)}>Show</button>
{!visible1 ? (
<div>
<h1>I am secret text</h1>
</div>
) : null}
</div>
<div className="panel">
<h3>Panel2</h3>
<button onClick={() => setVisible2(!visible2)}>Show</button>
{!visible2 ? (
<div>
<h1>I am secret text 2</h1>
</div>
) : null}
</div>
</div>
);
}
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [visible, setVisible] = useState(true);
const [ panel , setPanel ] = useState('Panel1');
const onHandleVisible = (value) => {
setPanel(value);
setVisible(!visible);
};
return (
<div className="App">
<div className="panel">
<h3>Panel1</h3>
<button onClick={() => onHandleVisible('Panel1')}>Show</button>
{!visible && panel === 'Panel1' ? (
<div>
<h1>I am secret text</h1>
</div>
) : null}
</div>
<div className="panel">
<h3>Panel2</h3>
<button onClick={() => onHandleVisible('Panel2')}>Show</button>
{!visible && panel === 'Panel2' ? (
<div>
<h1>I am secret text 2</h1>
</div>
) : null}
</div>
</div>
);
}
You can do with 1 state, just make that state as visiblePanel and update name of panel in that state to show any particular panel
https://codesandbox.io/s/ecstatic-dust-6vrv7
import "./styles.css";
export default function App() {
const [visiblePanel, setVisiblePanel] = useState(null);
const onHandleVisible = (panelName) => {
if(panelName === visiblePanel) {
setVisiblePanel(null);
} else {
setVisiblePanel(panelName);
}
};
return (
<div className="App">
<div className="panel">
<h3>Panel1</h3>
<button onClick={() => onHandleVisible('panel1')}>Show</button>
{visiblePanel === 'panel1' && (
<div>
<h1>I am secret text</h1>
</div>
)}
</div>
<div className="panel">
<h3>Panel2</h3>
<button onClick={() => onHandleVisible('panel2')}>Show</button>
{visiblePanel === 'panel2' && (
<div>
<h1>I am secret text 2</h1>
</div>
)}
</div>
</div>
);
}
You are using same variable for both use 2 variables to keep track which one is open.
https://codesandbox.io/s/blazing-fire-0dng2
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [visiblePanel1, setVisiblePanel1] = useState(true);
const [visiblePanel2, setVisiblePanel2] = useState(true);
const onHandleVisible = panel => {
if (panel === 1) {
setVisiblePanel1(!visiblePanel1);
} else if (panel === 2) {
setVisiblePanel2(!visiblePanel2);
}
};
return (
<div className="App">
<div className="panel">
<h3>Panel1</h3>
<button onClick={() => onHandleVisible(1)}>Show</button>
{!visiblePanel1 ? (
<div>
<h1>I am secret text</h1>
</div>
) : null}
</div>
<div className="panel">
<h3>Panel2</h3>
<button onClick={() => onHandleVisible(2)}>Show</button>
{!visiblePanel2 ? (
<div>
<h1>I am secret text 2</h1>
</div>
) : null}
</div>
</div>
);
}
Edit
If there are multiple panels
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [visible, setVisible] = useState(true);
const [panelName, setPanelName] = useState();
const onHandleVisible = panel => {
setVisible(!visible);
setPanelName(panel);
};
return (
<div className="App">
<div className="panel">
<h3>Panel1</h3>
<button onClick={() => onHandleVisible("panel1")}>Show</button>
{!visible && panelName === "panel1" ? (
<div>
<h1>I am secret text</h1>
</div>
) : null}
</div>
<div className="panel">
<h3>Panel2</h3>
<button onClick={() => onHandleVisible("panel2")}>Show</button>
{!visible && panelName === "panel2" ? (
<div>
<h1>I am secret text 2</h1>
</div>
) : null}
</div>
</div>
);
}
Also updated codesandbox.
Related
I am trying to create selected tab in Next.Js.
The User will have the option to search for data it can be Users or Posts, what the user will search for will be selected by clicking on one of the buttons.
Once the user clicks on the button the button will change background to blue.
However I can't make it to work properly, when the User clicks on the button the .Selected class gets added to the button but the button doesn't render the CSS.
import React, { MouseEventHandler, ReactElement, useState } from 'react'
import { PageWithLayout } from '../components/Layouts/LayoutConfig'
import MainLayout from '../components/Layouts/MainLayout'
import style from '../styles/Search.module.css'
const Search: PageWithLayout = () => {
const [searchPosts, setPostsSearch] = useState < String > ();
const setSearchOption = (searchFor: String) => {
let searchOption = '';
if (searchFor == 'POSTS') {
searchOption = 'POSTS';
} else {
searchOption = 'USERS';
let button = document.getElementById('usersOption') as HTMLElement;
button.className += style.Selected;
}
console.log(searchOption);
setPostsSearch(searchOption);
}
return (
<>
<div className='pageContent'>
<div className={style.SearchBarContainer}>
<div className={style.SearchContainer}>
<i className="fa-solid fa-magnifying-glass"></i>
<input className={style.SearchBar} type={'text'} placeholder='Search...' />
</div>
<div className={style.SearchOptions}>
<button id='usersOption' onClick={() => setSearchOption('USERS')}>Users</button>
<button id='postsOption' onClick={() => setSearchOption('POSTS')}>Posts</button>
</div>
</div>
<div className='SearchedContent'>
</div>
</div>
</>
)
}
Search.getLayout = function getLayout(page: ReactElement) {
return (
<MainLayout>
{page}
</MainLayout>
)
}
export default Search
you can use searchOption data for className style
import React, { MouseEventHandler, ReactElement, useState } from 'react'
import { PageWithLayout } from '../components/Layouts/LayoutConfig'
import MainLayout from '../components/Layouts/MainLayout'
import style from '../styles/Search.module.css'
const Search: PageWithLayout = () => {
const [searchPosts, setPostsSearch] = useState<String>();
return (
<>
<div className='pageContent'>
<div className={style.SearchBarContainer}>
<div className={style.SearchContainer}>
<i className="fa-solid fa-magnifying-glass"></i>
<input className={style.SearchBar} type={'text'} placeholder='Search...'/>
</div>
<div className={style.SearchOptions}>
<button id='usersOption' className={searchPosts === 'USERS' ? style.Selected : undefined } onClick={() => setPostsSearch('USERS')}>Users</button>
<button id='postsOption' className={searchPosts === 'POSTS' ? style.Selected : undefined } onClick={() => setPostsSearch('POSTS')}>Posts</button>
</div>
</div>
<div className='SearchedContent'>
</div>
</div>
</>
)
}
Search.getLayout = function getLayout(page: ReactElement){
return(
<MainLayout>
{page}
</MainLayout>
)
}
export default Search
Just have a state for active searchOption and apply the class conditionally directly into the JSX.
const [activeSearchOption, setActiveSearchOption] = useState('USERS')
return (
<>
<div className='pageContent'>
<div className={style.SearchBarContainer}>
<div className={style.SearchContainer}>
<i className="fa-solid fa-magnifying-glass"></i>
<input className={style.SearchBar} type={'text'} placeholder='Search...'/>
</div>
<div className={style.SearchOptions}>
<button id='usersOption' className={activeSearchOption === 'USERS' ? 'active' : ''} onClick={() => setSearchOption('USERS')}>Users</button>
<button id='postsOption' className={activeSearchOption === 'POSTS' ? 'active' : ''} onClick={() => setSearchOption('POSTS')}>Posts</button>
</div>
</div>
<div className='SearchedContent'>
</div>
</div>
</>
)
Please help! I don't know why I'm getting this error. I can't find what I need to change :( The needed output in browser is perfectly fine. But I am getting this error. I'm not used to list and keys on react. I have the latest versions of React and Nodejs and the packages needed
Homescreen.js:
import React, { useState, useEffect } from 'react'
import axios from 'axios';
import Room from '../components/Room';
import Loader from '../components/Loader';
import Error from '../components/Error';
function Homescreen() {
let [rooms, setrooms] = useState([]);
const [loading, setloading] = useState();
const [error, seterror] = useState();
useEffect(() => {
async function getResults() {
try {
seterror(false);
setloading(true);
const data = (await axios('/api/rooms/getallrooms')).data;
setrooms(data);
setloading(false);
} catch (e) {
seterror(true);
setloading(false);
}
}
getResults();
}, []);
return (
<div className='container'>
<div className='row justify-content-center mt-5'>
{loading ? (
<Loader />
) : rooms.length > 1 ? (
rooms.map(room => {
return <div className="col-md-9 mt-3">
<Room room={room} />
</div>;
})
) : (
<Error />
)}
</div>
</div>
)
}
export default Homescreen;
//<h1>{room.name}</h1>
and my Room.js:
import React, { useState } from "react";
import { Modal, Button, Carousel } from 'react-bootstrap'
import { First } from "react-bootstrap/esm/PageItem";
import { Link } from 'react-router-dom'
function Room({ room }) {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
< div className="row bs" >
<div className="col-md-4">
<img src={room.imageurls[0]} className="smallimg" />
</div>
<div className="col-md-7">
<h1>{room.name}</h1>
<b>
{" "}
<p>Max Count : {room.maxcount}</p>
<p>Phone Number : {room.phonenumber}</p>
<p>Type : {room.type}</p>
</b>
<div style={{ float: "right" }}>
<Link to={`/book/${room._id}`}>
<button className="btn btn-primary m-5">Book Now!</button>
</Link>
<button className="btn btn-primary" onClick={handleShow}>View Details</button>
</div>
</div>
<Modal show={show} onHide={handleClose} size='lg'>
<Modal.Header>
<Modal.Title>{room.name}</Modal.Title>
</Modal.Header>
<Modal.Body>
<Carousel prevLabel='' nextLabel=''>
{room.imageurls.map(url => {
return <Carousel.Item>
<img
className="d-block w-100 bigimg"
src={url}
/>
</Carousel.Item>
})}
</Carousel>
<p>{room.description}</p>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
</Modal.Footer>
</Modal>
</div>
);
}
export default Room;
Browser Console Error:
You have to give the first element in a map function a key:
rooms.map((room, index) => {
return (
<div key={index} className="col-md-9 mt-3">
<Room room={room} />
</div>
);
});
I already have the condition, but i need to set the state, if i setColor on the if method, give me error- Too many re-renders. React limits the number of renders to prevent an infinite loop.
State:
const [color, setColor] = useState();
Map:
{data.map((doc) => {
let verificacao = "";
if (doc.status === "Não Necessário") {
verificacao = "Proxima Verificação:";
setColor(true)
} else if (doc.status === "Verificado e Conforme") {
verificacao = "Data:";
setColor(false)
} else {
console.log("ERRO");
}
return (
The span i want to change the color:
<div className="row">
<div className="pontos">
<span className={color ? "red" : "green"}>
{doc.status}
</span>
<span className="data-status">{verificacao}</span>
{JSON.stringify(
doc.dateVerificado
.toDate()
.toISOString()
.replace(/T.*/, "")
.split("-")
.reverse()
.join("-")
)}
</div>
</div>
Full Code:
import React, { useEffect, useState } from "react";
import { Button } from "react-bootstrap";
import ManutencaoDataService from
"../../Services/ManutecaoDataService";
import "./ManutencaoInfo.css";
const ManutencaoInfo = ({ getDataId }) => {
const [data, setData] = useState([]);
const [color, setColor] = useState();
useEffect(() => {
getData();
return () => {
setData([]);
};
}, []);
const getData = async () => {
const data = await ManutencaoDataService.getAllData();
console.log(data.docs);
setData(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
};
const deleteHandler = async (id) => {
await ManutencaoDataService.deleteData(id);
getData();
};
return (
<>
<div className=" container mb-2">
<Button variant="dark edit" onClick={getData}>
Atualizar Lista
</Button>
</div>
{/* <pre>{JSON.stringify(books, undefined, 2)}</pre>} */}
{data.map((doc) => {
let verificacao = "";
if (doc.status === "Não Necessário") {
verificacao = "Proxima Verificação:";
setColor(true)
} else if (doc.status === "Verificado e Conforme") {
verificacao = "Data:";
setColor(false)
} else {
console.log("ERRO");
}
return (
<div key={doc.id} className="container-principal">
<div className="container">
<div className="row relatorio">
<div className="col">
<div className="departamento">
<h3>{doc.departamentos}</h3>
</div>
</div>
</div>
<div className="row detalhes">
<div className="col">
<div className="row">
<div className="pontos">
<span className="identificacao">Equipamento:
</span>
{doc.equipamentos}
</div>
</div>
<div className="row">
<div className="pontos">
<span className="identificacao">Responsável:
</span>
{doc.responsaveis}
</div>
</div>
<div className="row">
<div className="pontos">
<span className="codigo">{doc.codigos.codigo}
</span>
<span className="tipo">{doc.tipo}</span>
</div>
</div>
</div>
<div className="col ">
<div className="row">
<div className="pontos">
<span className="identificacao">Data Manutenção:
</span>
{JSON.stringify(
doc.dateManutencao
.toDate()
.toISOString()
.replace(/T.*/, "")
.split("-")
.reverse()
.join("-")
)}
</div>
</div>
<div className="row">
<div className="pontos">
<span className={color ? "red" : "green"}>
{doc.status}
</span>
<span className="data-status">{verificacao}</span>
{JSON.stringify(
doc.dateVerificado
.toDate()
.toISOString()
.replace(/T.*/, "")
.split("-")
.reverse()
.join("-")
)}
</div>
</div>
<div className="row">
<div className="pontos">{doc.codigos.observacoes}
</div>
</div>
</div>
</div>
<div className="row botoes">
<div className="col">
<span className="botao-editar">
<Button
variant="secondary"
className="edit"
onClick={(e) => getDataId(doc.id)}
>
Editar
</Button>
</span>
<span className="botao-apagar">
<Button
variant="danger"
className="delete"
onClick={(e) => deleteHandler(doc.id)}
>
Apagar
</Button>
</span>
</div>
</div>
</div>
</div>
);
})}
</>
);
};
export default ManutencaoInfo;
Instead of using state, I would recommend using doc's status property for using the correct CSS class like this:
<span className={doc.status === "Não Necessário" ? "red" : "green"}>
{doc.status}
</span>
import React, { useEffect, useState } from "react";
import { Button } from "react-bootstrap";
import ManutencaoDataService from
"../../Services/ManutecaoDataService";
import "./ManutencaoInfo.css";
import classNames from 'classnames';
const ManutencaoInfo = ({ getDataId }) => {
const [data, setData] = useState([]);
useEffect(() => {
getData();
}, []);
const getData = async () => {
const data = await ManutencaoDataService.getAllData();
console.log(data.docs);
setData(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
}
return (
<>
...
{data.map((doc) => {
return (
<div key={doc.id} className="container-principal">
<div className="container">
...
<div className="row detalhes">
...
<div className="col ">
...
<div className="row">
<div className="pontos">
<span className={classNames({red: doc.status === "Não Necessário", green:doc.status === "Verificado e Conforme" })}>
{doc.status}
</span>
<span className="data-status">{
doc.status === "Não Necessário" ? "Proxima Verificação:" : doc.status === "Verificado e Conforme" ? "Data:" :""
}</span>
....
</div>
</div>
....
</div>
</div>
...
</div>
</div>
);
})}
</>
);
};
export default ManutencaoInfo;
create a new component which renders inside the map function, it will be better to maintain
I think you are overcomplicating it with introducing state variable.
You can just use local variable in your function like this:
// Remove this state
// const [color, setColor] = useState();
{data.map((doc) => {
let verificacao = "";
let color; // add this var
if (doc.status === "Não Necessário") {
verificacao = "Proxima Verificação:";
color = 'red' // changed
} else if (doc.status === "Verificado e Conforme") {
verificacao = "Data:";
color = 'green' // changed
} else {
console.log("ERRO");
}
return (
// ...
<span className={color}> {/* changed */}
{doc.status}
</span>
// ...
)
Currently I have a component that is loaded when I call my API. This content has a CitizenshipType field that separates the items from each other. I have 2 buttons on top which I want to use to filter my data. 1 button is called Europe which should bring out all the content where CitizenshipType=Europe, etc. Currently I have all my data showing without any filtering. Here is my code:
Citizenship Page:
export default function Citizenship({ items, citi }) {
return (
<>
<div>
<div onClick=//SomeFunction>
CARRIBEAN
</div>
<div onClick=//SomeFunction>
EUROPE
</div>
</div>
<div>
<div onClick=//SomeFunction>
OTHER PROGRAMS
</div>
</div>
<div>
{items &&
items.map((item) => (
<div style={{ padding: "40px" }}>
<div class="citizen-item" key={item.id}>
<div className="container6">
<img
src={`http://localhost:1337${item.Thumbnail.url}`}
/>
<div>
{item.Title}
</div>
<div>
Access to {item.CountriesAccessible} countries
</div>
<div>
<button class="findButton">FIND OUT MORE</button>
</div>
</div>
</div>
</div>
))}
{citi &&
citi.map((test) => (
<div style={{ padding: "40px" }}>
<div class="citizen-item" key={test.id}>
<div className="container6">
<img
src={`http://localhost:1337${test.Thumbnail.url}`}
/>
<div>
{test.Title}
</div>
<div>
Access to {test.CountriesAccessible} countries
</div>
<div>
<button class="findButton">FIND OUT MORE</button>
</div>
</div>
</div>
</div>
))}
</>
);
}
Home Page where I am calling the APIs:
export default function Home({ items, citi }) {
return (
<div>
<Benefits />
<Citizenship items={items} citi={citi} />
<Video />
</div>
);
}
export async function getStaticProps() {
const CitizenshipEUres = await fetch(
"http://localhost:1337/citizenships?_limit=5&CitizenshipType=Europe"
);
const CitizenshipCAres = await fetch(
"http://localhost:1337/citizenships?_limit=5&CitizenshipType=Caribbien"
);
const items = await CitizenshipEUres.json();
const citi = await CitizenshipCAres.json();
return {
props: { items, citi },
};
}
you toggle them with states:
import React, { useState } from 'react'
export const TestComponent = () => {
const [carribeanIsShowing, setShowCarribean] = useState(false)
const [europeIsShowing, setShowEurope] = useState(false)
const toggleCarribean = () => {
if (!carribeanIsShowing) {
if(europeIsShowing) {
setShowEurope(false)
}
setShowCarribean(!carribeanIsShowing)
} else {
return
}
}
const toggleEurope = () => {
if (!europeIsShowing) {
if(carribeanIsShowing) {
setShowCarribean(false)
}
setShowEurope(!europeIsShowing)
} else {
return
}
}
return (
<div>
<button onClick={() => toggleCarribean()}>
CARRIBEAN
</button>
<button onClick={() => toggleEurope()}>
EUROPE
</button>
{europeIsShowing && <div>Europe</div>}
{carribeanIsShowing && <div>carribean</div>}
</div>
)
}
Create a new variable where you store the current CitizenshipType, with a default value of 'Europe'.
const [currentCitizenshipType, setCurrentCitizenshipType] = useState(
"Europe"
);
You change your onClick event
<div onClick={() => setCurrentCitizenshipType('Europe')}>
EUROPE
</div>
And finally add a filter statment to your items.map call:
{
items
.filter((item) => item.citizenshipType === currentCitizenshipType)
.map((item)
...}
This code:
How to display a dialog when a button is clicked using react and typescript?
I wanna open dialog from each todos, how to make it ? I used react js and typescript. Help me to resolve this problem.
interface ListProps {
todos: INote[];
onDelete: (title: string) => void;
}
const TodoList: React.FunctionComponent<ListProps> = ({ todos, onDelete }) => {
const [showAlert, setShowAlert] = useState(false);
const [todo, setTodos] = useState(null);
How to select each item by ts?It doesn't work. What is reason? Thanks!
const handleOpenDialog = (todos: any) => {
setTodos(todos);
setShowAlert(true);
};
const handleCloseDialog = () => {
setShowAlert(false);
};
return (
<>
<section className="list list--wrapper">
{todos.map((todos) => (
<div className="item list__item" key={todos.title}>
<span className="item__title">{todos.title}</span>
<div className="item__group">
<input
className="item__completed"
type="checkbox"
checked={todos.completed}
/>
<span className="item__decs">{todos.desc}</span>
</div>
<div className="item__btn">
<button
className="item__btnd"
onClick={() => handleOpenDialog(todos)}
>
Delete
</button>
<button className="item__btne">Edit</button>
</div>
{showAlert && todo && (
<AlertDialog
handleCloseDialog={handleCloseDialog}
title={todos.title}
/>
)}
</div>
))}
</section>
</>
);
};
export default TodoList;
just add a condition to only show the AlertDialog on selected todos
<section className="list list--wrapper">
{todos.map((todos) => (
<div className="item list__item" key={todos.title}>
<span className="item__title">{todos.title}</span>
<div className="item__group">
<input
className="item__completed"
type="checkbox"
checked={todos.completed}
/>
<span className="item__decs">{todos.desc}</span>
</div>
<div className="item__btn">
<button
className="item__btnd"
onClick={() => handleOpenDialog(todos)}
>
Delete
</button>
<button className="item__btne">Edit</button>
</div>
{showAlert && todos.title===todo?.title && (
<AlertDialog
handleCloseDialog={handleCloseDialog}
title={todos.title}
/>
)}
</div>
))}
</section>
or just move the AlertDialog outside the map
<section className="list list--wrapper">
{todos.map((todos) => (
<div className="item list__item" key={todos.title}>
<span className="item__title">{todos.title}</span>
<div className="item__group">
<input
className="item__completed"
type="checkbox"
checked={todos.completed}
/>
<span className="item__decs">{todos.desc}</span>
</div>
<div className="item__btn">
<button
className="item__btnd"
onClick={() => handleOpenDialog(todos)}
>
Delete
</button>
<button className="item__btne">Edit</button>
</div>
</div>
))}
{showAlert && todo && (
<AlertDialog
handleCloseDialog={handleCloseDialog}
title={todos.title}
/>
)}
</section>