Ant modal appears few times, but if i remove map function inside the modal then its works fine its appears only one time.
what may be the issue? please help me to solve this issue (Modal triggering/appears few times)
Ant modal code follows:
const [visibleVoucherModal, setVisibleVoucherModal] = useState(false);
const showVoucherModal = () => {
setVisibleVoucherModal(true)
}
const closeVoucherModal = () => {
setVisibleVoucherModal(false);
};
const SavedVoucherModal = () => {
return (
<Modal title="Select Any Voucher" visible={visibleVoucherModal} onCancel={closeVoucherModal} footer={null} >
{savedVoucherList.length >= 1 ?
<div>
<Checkbox.Group className="w-100" onChange={checkBox} value={voucherVal} >
{savedVoucherList.map((item, i) => {
return (
<div key={i}>
<Checkbox value={item.Id} className="w-100" onChange={e => { handleCheckBox(e, i) }}
checked={checked[i] || true} disabled={!checked[i] && disabled} >
<div className="pl-4">
<List.Item style={{ marginTop: "-35px" }} className="py-0">
<List.Item.Meta
// avatar={<img src={item.Photo == '' ? 'd' : item.Photo} alt="" width="72" />}
title={<span style={{ fontSize: "12px" }}>{item.Name}</span>}
description={<div className="small">Expiry Date: <br />{item.ExpireDate.slice(0, 10)}</div>}
/>
<div className="pt-1">
<p className="font-weight-bold text-primary mb-0">{numberFormat(item.Price)}</p>
<small><del>{numberFormat(item.OldPrice)}</del></small>
</div>
</List.Item>
</div>
</Checkbox>
<Divider className="m-0 p-0 mb-4" />
</div>)
})}
</Checkbox.Group>
</div> :
<p className="mb-4">Oops, there is no voucher applicable to this order</p>
}
<Button type="primary" className="font-weight-bold btn-round" onClick={closeVoucherModal}>Close</Button>
</Modal>
)
}
Button:
<Button type="default" className="text-primary border-right-0 border-left-0" size="large" onClick={showVoucherModal}>Redeem Voucher</Button>
Related
I have a react component that display a card with input and button.
I want when I click the button to display a spinner, meanwhile after button click there is an axios post request to write some data on server. the problem is I don't see the spinnet after I click the button, I only see the message after my request done (2-3 sec after click)
function User(props) {
const [memo, setMemo] = useState('');
const [isUpdated, setIsUpdated] = useState(false);
const [spinner, setSpinner] = useState(false);
const onClickForm = (e) => {
e.preventDefault();
let inputValue = document.getElementById(inputId);
setSpinner(true);
axios.post(url, {
body: {
"internalid": props.internalid,
"memo": memo
},
headers: {"Content-Type": "application/json"},
redirect: 'follow'
}).then(response => {
console.log(response.data[0]);
setSpinner(false);
if (response.data[0].Success) {
setIsUpdated(true);
}
}, (error) => {
setIsUpdated(true);
setSpinner(false);
console.log(error)
}
)
setMemo('')
inputValue.value = '';
}
return (
<div key={props.index}>
<form onSubmit={e => onClickForm(e)}>
<Card className="card" key={props.index}>
<Card.Content>
<Card.Header>{props.tranid}</Card.Header>
<Card.Description>
{props.name}
</Card.Description>
<br/>
{!isUpdated ? (
<div>
<Input id={inputId} placeholder='Write to memo'
onChange={(e) => setMemo(e.target.value)}/>
<br/>
<button style={{marginTop: 20}} className="ui inverted blue button">Submit Change
</button>
</div>
) : (
<div>
{!spinner ? <p style={{color: 'green'}}>UPDATED!</p> : <CircularProgress/>}
</div>
)
}
)}
</Card.Content>
</Card>
</form>
</div>
)
}
It seems that as the conditions are set, when !isUpdated then <CircularProgress /> may not render, even though spinner is true.
In the conditional render output, perhaps try:
{!isUpdated && !spinner && (
<div>
<Input
id={inputId}
placeholder="Write to memo"
onChange={(e) => setMemo(e.target.value)}
/>
<br />
<button style={{ marginTop: 20 }} className="ui inverted blue button">
Submit Change
</button>
</div>
)}
{!isUpdated && spinner && <CircularProgress />}
{isUpdated && !spinner && <p style={{ color: "green" }}>UPDATED!</p>}
Or if ternary operator is preferred:
{isUpdated ? (
<p style={{ color: "green" }}>UPDATED!</p>
) : spinner ? (
<CircularProgress />
) : (
<div>
<Input
id={inputId}
placeholder="Write to memo"
onChange={(e) => setMemo(e.target.value)}
/>
<br />
<button style={{ marginTop: 20 }} className="ui inverted blue button">
Submit Change
</button>
</div>
)}
I want to dynamically show my buttons when i get to the lastSlide, but it dies not seems to work.
I'm trying to use FindIndex to find someText that is actually on the lastSlide and nothing happens
The console prints out 4 because i have 5 items in the Array which is correct, but i can't render something to the dom
if there's any other options in the IonSlides Component itself, i will appreciate, because onSlideReachEnd event that ionic provides does not work.
const lastIndex = slideContent.findIndex((element) => {
if (element.slideTitle === "Safe & Secure") {
return true;
}
return false;
});
console.log(lastIndex); // 4
return (
<IonPage>
<div className="content">
<IonSlides pager={true} options={slideOpts}>
{slideContent.map((slide, idx) => (
<IonSlide key={idx}>
<div>
<img
src={slide.slideImage}
alt={slide.slideAltText}
className={slide.slideClassName}
/>
<IonText>
<h5 className="mb-1 fw-bold">{slide.slideTitle}</h5>
</IonText>
<IonText color="primary" className="fw-bold">
<h4 className="mt-0 bold h4"> {slide.slidePrimaryText} </h4>
</IonText>
<div className="pt-0 px-5 pb-4">
<IonText>
<h6 className="fs-md mb-6 line-h fw-sm fw-reg tet-color">
{slide.slideText}
{slide.slideSecoundaryText && (
<IonText color="primary" className="fw-bold ">
<h6 className="mt-0 fs-md bold mt-3">
{slide.slideSecondaryText}
</h6>
</IonText>
)}
</h6>
</IonText>
{slide.slideBtn && (
<IonButton
shape="round"
fill="clear"
className="btn f-inherit"
size="small"
>
Stuff
</IonButton>
)}
{idx}
</div>
</div>
</IonSlide>
))}
</IonSlides>
</div>
{lastIndex && (
<div className="ion-padding">
<IonGrid>
<IonRow>
<IonCol size="6">
<IonButton
expand="block"
className="btn"
size="small"
onClick={() => navigate("/login", "forward")}
>
Login
</IonButton>
</IonCol>
<IonCol size="6">
<IonButton
expand="block"
fill="outline"
onClick={() => navigate("/get-started", "forward")}
className="btn"
size="small"
>
Get Started
</IonButton>
</IonCol>
</IonRow>
</IonGrid>
</div>
)}
</IonPage>
);
const SlidePage = () => {
const [isLastSlide, setIsLastSlide] = useState();
const slideChanged = async e => {
const r = await e.target.isEnd();
setIsLastSlide(r);
console.log("isEnd", r);
};
return (
<IonPage>
<IonContent>
<IonSlides pager={true} onIonSlideDidChange={slideChanged}>
<IonSlide>
<h1>Slide 1</h1>
</IonSlide>
<IonSlide>
<h1>Slide 2</h1>
</IonSlide>
<IonSlide>
<h1>Slide 3</h1>
</IonSlide>
</IonSlides>
{isLastSlide && <h1 style={{ textAlign: "center" }}>IS LAST SLIDE</h1>}
</IonContent>
</IonPage>
);
listen for slide change event and update the state if it is the last slide.
onIonSlideDidChange
working example here on stackblitz - https://stackblitz.com/edit/react-w5gawb?file=src%2FApp.js
I have a list of icons.
When I click on one of them, I want it to :
1/ change state to day or night
2/ change icon image to a sun or a moon.
But with the code that I've written, if I click on one, it changes all the icons image and only one state is linked to all.
How can I do so each icons has it own state and when i click on icon, only the icon clicked changes to a moon or a sun and not all of them ?
My code :
export default function MyModal() {
const [isVisible, setVisible] = useState(false);
const [isDay, setDay] = useState(true);
const { RangePicker } = DatePicker;
const { Option } = Select;
const style = {
verticalAlign: "middle",
marginRight: 10,
};
function handleDayNight() {
isDay === true ? setDay(false) : setDay(true);
console.log("isDay =", isDay);
}
function handleSelectChange(value) {
console.log(`selected ${value}`);
}
function handleCheckChange(checkedValues) {
console.log("checked =", checkedValues);
}
return (
<div>
<Button type="primary" onClick={() => setVisible(true)}>
Add an exception
</Button>
<Modal
title="Add an exception"
style={{ top: 20 }}
visible={isVisible}
onOk={() => setVisible(false)}
onCancel={() => setVisible(false)}
>
<p>Exceptions name</p>
<Input placeholder="80% Wednesday" />
<p style={{ marginTop: 10 }}>Select date</p>
<RangePicker onChange={([date]) => console.log(date)} />
<p style={{ marginTop: 10 }}>Frequency</p>
<Select
defaultValue="Weekly"
style={{ width: 120 }}
onChange={handleSelectChange}
>
<Option value="daily">Daily</Option>
<Option value="weekly">Weekly</Option>
<Option value="monthly">Monthly</Option>
</Select>
<Divider />
<Checkbox.Group style={{ width: "100%" }} onChange={handleCheckChange}>
<div>
{isDay === true ? (
<Sun style={style} onClick={handleDayNight} />
) : (
<Moon style={style} onClick={handleDayNight} />
)}
<Checkbox value="Monday">Monday</Checkbox>
<br></br>
{isDay === true ? (
<Sun style={style} onClick={handleDayNight} />
) : (
<Moon style={style} onClick={handleDayNight} />
)}
<Checkbox value="Tuesday">Tuesday</Checkbox>
<br></br>
{isDay === true ? (
<Sun style={style} onClick={handleDayNight} />
) : (
<Moon style={style} onClick={handleDayNight} />
)}
<Checkbox value="Wednesday">Wednesday</Checkbox>
<br></br>
{isDay === true ? (
<Sun style={style} onClick={handleDayNight} />
) : (
<Moon style={style} onClick={handleDayNight} />
)}
<Checkbox value="Thursday">Thursday</Checkbox>
<br></br>
<Checkbox value="Friday">Friday</Checkbox>
<br></br>
<Checkbox value="Saturday">Saturday</Checkbox>
<br></br>
<Checkbox value="Sunday">Dimanche</Checkbox>
</div>
</Checkbox.Group>
</Modal>
</div>
);
}
Use a separate component for each of those, so you can have individual separate states inside those components. Eg, replace all of
{isDay === true ? (
<Sun style={style} onClick={handleDayNight} />
) : (
<Moon style={style} onClick={handleDayNight} />
)}
with
<SunMoon style={style} />
const SunMoon = ({ style }) => {
const [isDay, setDay] = useState(true);
const handleDayNight = () => setDay(!isDay);
return isDay
? <Sun style={style} onClick={handleDayNight} />
: <Moon style={style} onClick={handleDayNight} />;
};
I am making a page which is paginated however I am at the moment rendering these in the render() method. I understand this is not ideal and I am almost sure this is why sometimes upon navigation to the screen the page numbers do not appear(they appear after a refresh of the page)
Essentially all I want is to take these out of the render method but I have allot going on in the render method at the moment So I am stuck on how to transition this.
I have included this code If you could advise how to take these out I will be very greatful.
Whole class
import React from "react";
import { Link } from "react-router-dom";
import { Modal, DropdownButton, Dropdown } from "react-bootstrap";
import ReactDOM from "react-dom";
var goToken = false;
var results = [];
class AdminWorkstations extends React.Component {
constructor() {
super();
this.state = {
questions: [],
viewDetails: false,
currentPage: 1,
todosPerPage: 5
};
this.getQuestionByUniqueDate = this.getQuestionByUniqueDate.bind(this);
// this.test = this.test.bind(this);
}
// sets the questions form sql into state for questions
handleClick = event => {
this.setState({
currentPage: Number(event.target.id)
});
};
handlePageChange(pageNumber) {
this.setState({ activePage: pageNumber });
}
componentDidMount() {
fetch(`/admin-completed-workstations`)
.then(recordset => recordset.json())
.then(results => {
this.setState({ questions: results.recordset });
console.log(this.state.questions);
this.state.questions &&
this.getQuestionByUniqueDate(this.state.questions);
});
}
getQuestionByUniqueDate(questions) {
for (var i = 0; i < questions.length; i++) {
if (
!results.find(q => q.Date == questions[i].Date) ||
!results.find(
q => q.AssignedWorkStation == questions[i].AssignedWorkStation
)
) {
results.push(questions[i]);
this.setState({ amountOfWorkstations: results.length });
}
}
return results;
}
render() {
const { currentPage, todosPerPage } = this.state;
// Logic for displaying current todos
const indexOfLastTodo = currentPage * todosPerPage;
const indexOfFirstTodo = indexOfLastTodo - todosPerPage;
const currentTodos = results.slice(indexOfFirstTodo, indexOfLastTodo);
const pageNumbers = [];
for (
let i = 1;
i <= Math.ceil(this.state.amountOfWorkstations / todosPerPage);
i++
) {
pageNumbers.push(i);
}
const renderPageNumbers = pageNumbers.map(number => {
return (
<button
className="btn btn-primary"
key={number}
id={number}
onClick={this.handleClick}
>
{number}
</button>
);
});
const renderTodos = currentTodos.map(r => {
return (
<>
<div className="jumbotron">
<Questions
workStation={r.AssignedWorkStation}
date={r.Date}
completeToken={r.CompleteToken}
>
{" "}
</Questions>
</div>
</>
);
});
let selectedWorkStation = window.localStorage.getItem("Workstation");
console.log(this.state.questions);
if (this.state.questions.length) {
return (
<div>
<h2 style={{ textAlign: "center" }}>
Completed Workstation Assessments
</h2>
<ul>
<button disabled className="btn btn-secondary">
Workstation Assessments
</button>
<Link to="./admin-center">
<button className="btn btn-secondary">Edit Questions</button>
</Link>
<Link to="./admin-center-view-users">
<button className="btn btn-secondary">View Users</button>
</Link>
<DropdownButton
style={{ float: "right" }}
id="dropdown-basic-button"
title="Completed"
>
<Dropdown.Item>
{" "}
<Link to="admin-view-workstation-assessments-declined">
In Progress
</Link>
</Dropdown.Item>
</DropdownButton>{" "}
</ul>
<ul>
{renderTodos}{" "}
<div
style={{ userSelect: "none", cursor: "pointer" }}
id="page-numbers"
>
{renderPageNumbers}
</div>
</ul>
</div>
);
} else if (!this.state.questions.length) {
return (
<>
{" "}
<div>
<h3 style={{ textAlign: "center" }}></h3>
<ul>
<br />
<br />{" "}
<div>
<h6>
{" "}
<tr>
Desk Location Selected :{" "}
<u style={{ color: "grey" }}>{selectedWorkStation}</u>
</tr>
</h6>
</div>
<div className="jumbotron">
<li style={{ textAlign: "center" }}>
<b>no completed Workstation Self-Assessments</b>{" "}
</li>
</div>
</ul>
</div>
</>
);
}
}
}
Just render method
render() {
const { currentPage, todosPerPage } = this.state;
// Logic for displaying current todos
const indexOfLastTodo = currentPage * todosPerPage;
const indexOfFirstTodo = indexOfLastTodo - todosPerPage;
const currentTodos = results.slice(indexOfFirstTodo, indexOfLastTodo);
const pageNumbers = [];
for (
let i = 1;
i <= Math.ceil(this.state.amountOfWorkstations / todosPerPage);
i++
) {
pageNumbers.push(i);
}
const renderPageNumbers = pageNumbers.map(number => {
return (
<button
className="btn btn-primary"
key={number}
id={number}
onClick={this.handleClick}
>
{number}
</button>
);
});
const renderTodos = currentTodos.map(r => {
return (
<>
<div className="jumbotron">
<Questions
workStation={r.AssignedWorkStation}
date={r.Date}
completeToken={r.CompleteToken}
>
{" "}
</Questions>
</div>
</>
);
});
let selectedWorkStation = window.localStorage.getItem("Workstation");
console.log(this.state.questions);
if (this.state.questions.length) {
return (
<div>
<h2 style={{ textAlign: "center" }}>
Completed Workstation Assessments
</h2>
<ul>
<button disabled className="btn btn-secondary">
Workstation Assessments
</button>
<Link to="./admin-center">
<button className="btn btn-secondary">Edit Questions</button>
</Link>
<Link to="./admin-center-view-users">
<button className="btn btn-secondary">View Users</button>
</Link>
<DropdownButton
style={{ float: "right" }}
id="dropdown-basic-button"
title="Completed"
>
<Dropdown.Item>
{" "}
<Link to="admin-view-workstation-assessments-declined">
In Progress
</Link>
</Dropdown.Item>
</DropdownButton>{" "}
</ul>
<ul>
{renderTodos}{" "}
<div
style={{ userSelect: "none", cursor: "pointer" }}
id="page-numbers"
>
{renderPageNumbers}
</div>
</ul>
</div>
);
} else if (!this.state.questions.length) {
return (
<>
{" "}
<div>
<h3 style={{ textAlign: "center" }}></h3>
<ul>
<br />
<br />{" "}
<div>
<h6>
{" "}
<tr>
Desk Location Selected :{" "}
<u style={{ color: "grey" }}>{selectedWorkStation}</u>
</tr>
</h6>
</div>
<div className="jumbotron">
<li style={{ textAlign: "center" }}>
<b>no completed Workstation Self-Assessments</b>{" "}
</li>
</div>
</ul>
</div>
</>
);
}
}
}
I am stuck in this problem. I want to add/remove the class on a header element on scroll, but somehow I can not manage it.
I tried to mount and unmount (found few solutions here on Stack) but does not work in my case. Simply because in most of those cases the code relates to component but I have a little bit different set-up.
Here the full code:
https://codesandbox.io/s/angry-villani-lduor?fontsize=14
I want to add the new class on store_details_header
const handleChangeIndex = index => {
setValue(index);
};
if (!selectedStore) {
return null;
}
return (
<div className="store-details">
<div className="store-details__header" style={{ backgroundImage: `url(${selectedStore.headerBackgroundImgUrl})` }}>
<img className="store-details__header__exit" src={exit} alt="exit" onClick={backToNearYou} />
<img className="store-details__header__logo" src={selectedStore.headerLogoUrl} alt="logo" />
</div>
<div className="store-details__content" style={{ backgroundImage: `url(${selectedStore.contentBackgroundImgUrl})` }}>
<div>
<AppBar className={props.classes.root} position="static" color="default">
<Tabs value={value} classes={{ indicator: props.classes.indicator }} onChange={setSelectedNavigationItem} variant="fullWidth">
<StyledTab label="Products" />
<StyledTab label="Items" />
</Tabs>
</AppBar>
<SwipeableViews axis={'x'} index={value} onChangeIndex={handleChangeIndex}>
<TabContainer>
{' '}
<div className="store-details__content__items">{renderSliderItems()}</div>
</TabContainer>
<TabContainer>
{' '}
<div className="store-details__content__items">{renderSliderItems()}</div>
</TabContainer>
</SwipeableViews>
</div>
</div>
{guestMode && renderGuestModeBox()}
{selectedStore.loyaltyCard && renderLoyaltyCard()}
</div>
);
};
const handleChangeIndex = index => {
setValue(index);
};
if (!selectedStore) {
return null;
}
return (
<div className="store-details">
<div className="store-details__header" style={{ backgroundImage: `url(${selectedStore.headerBackgroundImgUrl})` }}>
<img className="store-details__header__exit" src={exit} alt="exit" onClick={backToNearYou} />
<img className="store-details__header__logo" src={selectedStore.headerLogoUrl} alt="logo" />
</div>
<div className="store-details__content" style={{ backgroundImage: `url(${selectedStore.contentBackgroundImgUrl})` }}>
<div>
<AppBar className={props.classes.root} position="static" color="default">
<Tabs value={value} classes={{ indicator: props.classes.indicator }} onChange={setSelectedNavigationItem} variant="fullWidth">
<StyledTab label="Products" />
<StyledTab label="Items" />
</Tabs>
</AppBar>
<SwipeableViews axis={'x'} index={value} onChangeIndex={handleChangeIndex}>
<TabContainer>
{' '}
<div className="store-details__content__items">{renderSliderItems()}</div>
</TabContainer>
<TabContainer>
{' '}
<div className="store-details__content__items">{renderSliderItems()}</div>
</TabContainer>
</SwipeableViews>
</div>
</div>
{guestMode && renderGuestModeBox()}
{selectedStore.loyaltyCard && renderLoyaltyCard()}
</div>
);
};