I have a following structure in React, but whenever I click on the buttons, the rendering is not changed:
function App() {
const [showTxt1, setShowTxt1] = useState(false);
const [showTxt2, setShowTxt2] = useState(false);
const setShowButtons = (selected) => {
console.log("selected:", selected);
setShowTxt1(selected === "txt1");
setShowTxt2(selected === "txt2");
}
return (
<React.Fragment>
<div className="main">
<div className="main-options">
<button
type="button"
className="btn btn-primary"
onClick={() => {
setShowButtons("txt1");
}}
>
Show Txt1
</button>
<button
type="button"
className="btn btn-primary"
onClick={() => {
setShowButtons("txt2");
}}
>
Show Txt2
</button>
</div>
{
showTxt1 && <p>text1</p>
}
{showTxt2 && <p>text2</p>
}
</div>
</React.Fragment>
);
}
I see the log on the console, but the page is not updated. On the 'Components' tab in debugging, I only get an error message: 'Timed out, while inspecting...'
This is a simplified version of my app, where I think the issue is.
Sometimes when I open a new tab (and thus the debugger is closed), it works. What can cause the issue?
Related
I have a textarea and a button. The button is disabled by default and when the user starts typing, I enable the button to be clicked. But the problem is that, the onClick function is not called while already disabled = false was set.
I've seen this: button onClick doesn't work when disabled=True is initialized (Reactjs)
Seems to be a good idea, but after I setState with the new value, my component is re-rendering, and I don't really want that.
const refText = useRef(null);
const refBtn = useRef(null);
function handleBtnStatus(e) {
let text = e.target.value;
if(text.replace(/\s/g, "").length > 0) {
refBtn.current.disabled = false;
}
else {
refBtn.current.disabled = true;
}
}
function postThis() {
console.log("You posted! Text:", refText.current.value);
// disable again
refBtn.current.disabled = true;
// delete previous text wrote
refText.current.value = "";
}
return (
<>
{isLogged && (
<div className="container">
<div className="content">
<div className="utool-item-text">
<textarea name="textArea" placeholder="Write something.." ref={refText} onChange={(e) => handleBtnStatus(e)}></textarea>
</div>
<div className="utool-item-post">
<button className="ust-btn-post" ref={refBtn} disabled={true} onClick={postThis}>Da Tweet</button>
</div>
</div>
<div className="posts-section">
<div className="list-posts">
{posts.map((p) => {
return (p.hidden === false ? (
<div className="post" key={p.id}>
<div className="post-text">
<span>{p.text}</span>
</div>
</div>
) : (''))
})}
</div>
</div>
</div>
)}
</>
)
Any help?
Use state instead of refs, re-rendering is ok for your case
Simplified example:
import React, { useState } from 'react';
const SimpleExample = () => {
const [textAreaValue, setTextAreaValue] = useState('');
return (
<>
<button disabled={!textAreaValue} onClick={() => console.log('onClick handler')}>
click me
</button>
<textarea value={textAreaValue} onChange={(e) => setTextAreaValue(e.target.value)} />
</>
);
};
And I would recommend checking this Use state or refs in React.js form components?
I have created a carousel which is a column of ten dates ,for this i am mapping dates by momentjs, Inside each of this column , i am mapping different time slots for morning ,afternoon and evening,
and i have a functionality that only shows first two time slots and then there is a show more button, by clicking on this button more time slots are appear,but whenver i am clicking on this button all of the columns time slots is appearing, i have to handle all the column button individually..
Thank You in adavance... :)
below is my code...
const [showMoreClicked, setShowMoreClicked] = useState(false);
const [showMoreAfternoon, setShowMoreAfternoon] = useState(false);
const [showMoreEvening, setShowMoreEvening] = useState(false);
const showMoreSlotsForMorning = (e) => {
e.preventDefault();
setMoreClicked(!showMoreClicked);
};
const showMoreSlotsForAfternoon = (e) => {
e.preventDefault();
setShowMoreAfternoon(!showMoreAfternoon);
};
const showMoreSlotsForEvening = (e) => {
e.preventDefault();
setShowMoreEvening(!showMoreEvening);
};
<Carousel responsive={responsive}>
{nexttendates.map((elem, dateIndex) => {
return (
<div>
<button key={dateIndex} className="nexttendates">
{elem}
</button>
<div className="appointment-timelots">
<div className="availableslots">
<div className="availableslot">
<img
src="../elements/doctorlist/doctorcard/sunrise.png"
alt=""
className="sunrise"
/>
Morning
</div>
</div>
</div>
{morningtime.map((elem, morInd, arr) => {
if (showMoreClicked == false) {
while (morInd == 0 || morInd == 1)
return (
<button key={morInd} className="appointtimes">
{elem}
</button>
);
} else {
return (
<button key={morInd} className="appointtimes">
{elem}
</button>
);
}
})}
<button
choseIndex={dateIndex}
onClick={showMoreSlotsForMorning}
className="appointtimes"
>
{showMoreClicked ? "Show Less" : "Show More"}
</button>
<img
src="../elements/doctorlist/doctorcard/sun.png"
alt=""
className="afternoon"
/>
Afternoon
{afternoontime.map((elem, aftInd) => {
if (showMoreAfternoon == false) {
while (aftInd == 0 || aftInd == 1)
return (
<button className="appointtimes">{elem}</button>
);
} else {
return (
<button className="appointtimes">{elem}</button>
);
}
})}
<button
choseIndex={dateIndex}
onClick={showMoreSlotsForAfternoon}
className="appointtimes"
>
{showMoreAfternoon ? "Show Less" : "Show More"}
</button>
<img
src="../elements/doctorlist/doctorcard/night-mode.png"
alt=""
className="evening"
/>
Evening
{eveningtime.map((elem, eveInd) => {
if (showMoreEvening == false) {
while (eveInd == 0 || eveInd == 1) {
return (
<button className="appointtimes">{elem}</button>
);
}
} else {
return (
<button className="appointtimes">{elem}</button>
);
}
})}
<button
choseIndex={dateIndex}
onClick={showMoreSlotsForEvening}
className="appointtimes"
>
{showMoreEvening ? "Show Less" : "Show More"}
</button>
</div>
);
})}
</Carousel>
i think its happening because of i have mapped an array and only used one useState to check open or not...Can anybody plz help me....
Make the time slots list as a separate component, so that each of the morning, afternoon, and evening list will have their own state automatically for toggling display.
Something like this example:
import { useState } from "react";
// Toggle showMore value on click
const SlotsList = ({ slots }) => {
const [showMore, setShowMore] = useState(false);
const handleShowMoreClick = () => {
setShowMore((prev) => !prev);
};
// Filter the slots prop before map it if showMore is false
return (
<div>
{slots
.filter((elem, index) => (showMore ? true : index <= 1))
.map((elem, index) => (
<button key={index} className="appointtimes">
{elem}
</button>
))}
<button onClick={handleShowMoreClick} className="appointtimes">
{showMore ? "Show Less" : "Show More"}
</button>
</div>
);
};
export default SlotsList;
In this example, the list is filtered before being mapped out for an easier solution. The key property should be replaced by a unique ID to avoid conflict.
It can then be imported and used like below in the main component. Also reusable for all 3 lists, and each have separate display toggle.
<SlotsList slots={morningtime} />
I am creating a data table, fetching data from Redux store, and setting up this Redux's raw data into a useState hook named rowsData, setRowsData for data table rows,
The data from redux is array of objects.
I then set the rowsData into a new [data, setData] useState because of some additional data, like meta information for pagination.
useEffect(() => {
const rawRows =
users.allUsers &&
users.allUsers.data.map((user) => {
return {
name: (
<Link
to={`/users/profile/view/${user.secondaryId}`}
className="d-flex justify-content-start align-items-center"
>
<div className="me-3">
<AvatarWord initial={user.name[0]} />
</div>
<h5 className="text-primary mt-2"> {user.name}</h5>
</Link>
),
primaryRole: primaryRoleBackground(
user.primary_role
? user.primary_role.name[0].toUpperCase() +
user.primary_role.name.slice(1)
: ""
),
// primary_role: primaryRoleBackground(user.primary_role),
id: user.id,
email: user.email,
status: <div>{userStatus(user.status, user.id)}</div>,
Here I am adjusting it according to data table. The last line ````Status: ``` has a function to discriminate the active and inactive users with a button to activate or deactivate them.
const userStatus = (status, id) => {
switch (status) {
case "0":
return (
<>
<span className="legend-indicator bg-danger text-dark"></span>
Inactive
<Link
to="#!"
type="button"
className="btn badge bg-success ms-2"
onClick={() => userActivator(id)}
>
Activate
</Link>
</>
);
case "1":
return (
<>
<span className="legend-indicator bg-success text-dark"></span>
Active
<Link
to="#!"
type="button"
className="btn badge bg-danger ms-2"
onClick={() => userDeactivator(id)}
>
Deactivate
</Link>
</>
);
default:
return;
}
};
Here is the output of the codes above.
now when I click on deactivate I use the following code to update the data.
const userDeactivator = (id) => {
// deactivateUser(id);
console.log(rowsData.length);
for (let i = 0; i === dataLength; i++) {
const res = rowsData[i].id === id;
setRowsData([
...rowsData,
{
...res,
status: (
<div>
<>
<span className="legend-indicator bg-danger text-dark"></span>
Inactive
<Link
to="#!"
type="button"
className="btn badge bg-success ms-2"
onClick={() => userActivator(res.id)}
>
Activate
</Link>
</>
</div>
),
},
]);
}
};
I sure sends the API call to deactivate the user, but I have to update the data status in runtime. What I am missing I cannot figure out.
In useEffect hook you have to pass the argument of status like this:
useEffect(() => {
return () => {
// Your Code
}
}, [status])
This would tell the useEffect that whenever the status changes you have to re-render the state for it.
This should be easy but of course I can't figure it out :)
Basically I've implemented a "load more" button when there are more items to display from array but when it reaches the end, I'd like to hide it. The code below doesn't work and I have a feeling it's because it need to check the index of the array and if it's at the end, then hide the button but I am unsure of how to go about the syntax. Thanks
import { useState } from 'react'
import releases from "../data/releases.json";
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import '../main.css'
const Release = () => {
// get first 12 items in array & load next 12 with "see more button"
const STEP = 12;
const [items, setItems] = useState(releases.slice(0, STEP));
const loadMore = () => {
setItems([...items, ...releases.slice(items.length, items.length + STEP)]);
};
return (
<Wrapper>
<div className="release fadein">
{items.map((item, i) => (
<div className="item" key={i}>
<Link to={`/release/${item.id}`}>
<img src={item.imageURL} alt={item.artist} />
</Link>
</div>
))}
{/* code that isn't working here */}
{items ? <button onClick={loadMore} className="btn" > show more </button> : <button className="btn hidden" ></button>}
</div>
</Wrapper >
)
}
when the items are less than 12 the button will not be displayed
{items%12 ===0 ? <button onClick={loadMore} className="btn" > show more </button> : nul}
I'm working on this little React project, and I have 4 buttons that have different titles for provided services. I also have a Modal that appears to give more information. I am using state to display and remove the Modal component which works fine. So I am looking for a way to pass different titles, and different sets of descriptions as props to the Modal depending on which button was pressed. I.E, if Button 4 was pressed, it would display the title and description text for Service 4.
Here is the current code I have
const ServicesCard: React.FC = () => {
const [modal, setModal] = useState(false);
const Toggle = () => setModal(!modal);
return (
<div className={classes.ServicesCard}>
<div className={classes.ServicesCardContainer}>
<div className={classes.TitleContainer}>
<h2>Services</h2>
<hr />
</div>
<div className={classes.ButtonContainer}>
<button onClick={() => Toggle()} id="s1">
Service 1
</button>
<button onClick={() => Toggle()} id="s2">
Service 2
</button>
<button onClick={() => Toggle()} id="s3">
Service 3
</button>
<button onClick={() => Toggle()} id="s4">
Service 4
</button>
<ServiceModal show={modal} close={Toggle} title="Service">
</ServiceModal>
</div>
<p>Click For More Info</p>
</div>
</div>
);
};
Any help would be greatly appreciated.
Your course of action should be passing props of whatever you want to display in the modal to the ServiceModal component.
I would suggest that instead of having a modal state, have a selectedService state which starts as null. Then, when clicking a button, change the selectedService state to whatever you chose and display the modal only when selectedService is not null
It would look something along these lines
const SERVICES_INFO = {
s1: {title: 'whatever', description: 'whatever'},
s2: //You get the gist
...
}
const ServicesCard: React.FC = () => {
const [selectedService, setSelectedService] = useState(false);
const selectService = service => setSelectedService(service);
const closeModal = () => setSelectedService(null);
return (
<div className={classes.ServicesCard}>
<div className={classes.ServicesCardContainer}>
<div className={classes.TitleContainer}>
<h2>Services</h2>
<hr />
</div>
<div className={classes.ButtonContainer}>
<button onClick={() => selectService("s1")} id="s1">
Service 1
</button>
<button onClick={() => selectService("s2")} id="s2">
Service 2
</button>
<button onClick={() => selectService("s3")} id="s3">
Service 3
</button>
<button onClick={() => selectService("s4")} id="s4">
Service 4
</button>
<ServiceModal show={selectedService !== null} close={closeModal} serviceInfo={SERVICES_INFO[selectedService]}>
</ServiceModal>
</div>
<p>Click For More Info</p>
</div>
</div>
);
};
And then in your ServiceModal component you can use the serviceInfo prop to render whatever you need.
I do not work in React Js. But I am telling you the Javascript.
Do this:
Give IDs to your Modal Title and Text like modalTitle and modalText.
Now, change the innerText of your title and text when a specific
button is clicked
modalTitle = documet.getElementById('modalTitle');
modalText = documet.getElementById('modalText');
//if button 1 is clicked
s1.addEventListner('click', ()=>{
modalTitle.innerText = 'Your Button s1 Title';
modalText.innerText = 'Your Button s1 Text';
})
//if button 2 is clicked
s2.addEventListner('click', ()=>{
modalTitle.innerText = 'Your Button s2 Title';
modalText.innerText = 'Your Button s2 Text';
})
Do this for all buttons.