Passing props to reactjs-popup component - javascript

I'm working on a Docusaurus project which is based on React, I wanted to add a popup modal with a title and an image inside.
For the Modal I use reactjs-popup, eveything works fine only the title and image do not appear.
This is where I import the Modal:
import Modal from '../../components/Modal.js';
<Modal image="img/test.png" title="test" />
This is the Modal component:
const Modal = ({ image, title }) => (
<Popup
trigger={
<button type="button" className="button">
Vezi exemplu!
</button>
}
modal
contentStyle={contentStyle}
nested
>
{close => (
<div className="modal">
<button className="close" onClick={close}>
×
</button>
<div className="content">
<h1>{title}</h1>
<img src={image} />
</div>
<div className="actions">
<button
type="button"
className="button"
onClick={() => {
console.log('modal closed ');
close();
}}
>
close
</button>
</div>
</div>
)}
</Popup >
);
Modal.propTypes = {
image: PropTypes.string,
title: PropTypes.string
}

instead of const Modal = ({ image, title }) => ( , type as
const Modal = props => {const {image = "", title = ""} = props;
then make a return function
return( <Popup
trigger={
<button type="button" className="button">
Vezi exemplu!
</button>
}
modal
contentStyle={contentStyle}
nested
>
{close => (
<div className="modal">
<button className="close" onClick={close}>
×
</button>
<div className="content">
<h1>{title}</h1>
<img src={image} />
</div>
<div className="actions">
<button
type="button"
className="button"
onClick={() => {
console.log('modal closed ');
close();
}}
>
close
</button>
</div>
</div>
)}
</Popup >);
}
your all code should look like this.
const Modal = props => {const {image = "", title = ""} = props;
return( <Popup
trigger={
<button type="button" className="button">
Vezi exemplu!
</button>
}
modal
contentStyle={contentStyle}
nested
>
{close => (
<div className="modal">
<button className="close" onClick={close}>
×
</button>
<div className="content">
<h1>{title}</h1>
<img src={image} />
</div>
<div className="actions">
<button
type="button"
className="button"
onClick={() => {
console.log('modal closed ');
close();
}}
>
close
</button>
</div>
</div>
)}
</Popup >);}

Related

react js how to add box counter

I want to add box in a counter in react js counter, but I do not know how to add in this application. I tried a lot after counter using react box material.
Here is my code of app.js like as this image shown:
`
import React, {useState} from "react";
import { Button} from 'react-bootstrap';
function App() {
const [count, setCount] = useState(0);//initial value is in parenthesis
return (
<div className="container my-10">
<div className="card text-center my-5">
<div className="card-body">
<h1>Counter App</h1>
<div className="my-5">
<h2 className="my-5">{count}</h2>
<div className="text-right">
<button
className="text-right rounded-circle btn btn-success mx-3"
onClick={() => setCount(count+1)}>+</button>
<button
className="rounded-circle btn btn-success mx-3"
onClick={() => setCount(count-1)}
disabled={count === 0}>-</button>
<Button type="reset"
onClick={() => setCount(0)}
disabled={count === 0}>Reset</Button>
</div>
</div>
</div>
</div>
</div>
);
}
export default App;
you mean something like this https://codesandbox.io/s/friendly-mclean-iuh9ig?file=/src/App.js:0-1415
import React, { useState } from "react";
import { Button } from "react-bootstrap";
function App() {
const [count, setCount] = useState(0); //initial value is in parenthesis
return (
<div className="container my-10">
<div className="card text-center my-5">
<div className="card-body">
<h1>Counter App</h1>
<div className="my-5">
<h2 className="my-5">{count}</h2>
<div className="text-right">
<button
className="text-right rounded-circle btn btn-success mx-3"
onClick={() => setCount(count + 1)}
>
+
</button>
<button
className="rounded-circle btn btn-success mx-3"
onClick={() => {
if (count > 0) {
setCount(count - 1);
}
}}
disabled={count === 0}
>
-
</button>
<Button
type="reset"
onClick={() => setCount(0)}
disabled={count === 0}
>
Reset
</Button>
</div>
</div>
{[...Array(count).keys()].map((item) => (
<div className="card">box {item + 1}</div>
))}
</div>
</div>
</div>
);
}
export default App;

How do I add some HTML panels from my Modal to my web page the 'React way'

I have 2 Components, ApplicationOverview.js and ApplicationModal.jsx. Basically, I have a button "Add Application" on my ApplicationOverview.js page which opens the Modal in which I want to fill in some input fields and upload an image there, which is then shown on the ApplicationOverview page as a panel through predefined HTML.
The way I currently implemented it is with the .insertAdjacentHTML method which works, but on the one hand I've been told that implementing it this way makes my page vulnerable to XSS, and on the other hand, events that are added like this are not working. Is there a safe way to let React handle this by passing the HTML to ApplicationOverview.js and append it to an existing div element? Nothing I have searched for so far has worked for me.
ApplicationModal.jsx:
import React from "react";
import placeholder from "../icons/placeholder.png";
var name = "";
var comment = "";
var filename = "";
var id = 0;
const ApplicationModal = ({ setOpen }) => {
const [state, setState] = React.useState("");
const [stateComment, setStateComment] = React.useState(placeholder);
const [file, setFile] = React.useState({placeholder});
React.useEffect(() => {
function handleEscapeKey(event) {
if (event.code === "Escape") {
setOpen(false);
}
}
document.addEventListener("keydown", handleEscapeKey);
return () => document.removeEventListener("keydown", handleEscapeKey);
});
const handleComment = (e) => {
setStateComment(e.target.value);
};
const handleChange = (e) => {
setState(e.target.value);
};
//Method which adds new panels to ApplicationOverview.js
const addNewApplication = () => {
if (state !== "" && stateComment !== "") {
document
.getElementById("center")
.insertAdjacentHTML(
"beforeend",
`<div class='overview-box' id=${id}> <img class='image' src=${file} alt='placeholder'/> <div class='box-content'><h3 class='overview-h3' id='new-headline'>${state}</h3> <p class='overview-p'>${stateComment}</p><h3 class='overview-h3-second'>Connected Products</h3><h1 class='overview-h1-second'> ?/? <p class='overview-p-second'>Online</p> </h1> <div class='module-button' id='configure'> <button type='button' class='btn btn-secondary'></button> <div class='button-animation'></div> <div class='button-content'> <span class='content-text'>Configure</span> </div> </div> </div> </div>`
);
id++;
setOpen(false);
} else if (state === "" && stateComment !== "") {
document
.getElementById("center")
.insertAdjacentHTML(
"beforeend",
`<div class='overview-box' id = ${id}> <img class='image' src=${file} alt='placeholder'/> <div class='box-content'><h3 class='overview-h3' id='new-headline'>${state}</h3> <p class='overview-p'>${stateComment}</p><h3 class='overview-h3-second'>Connected Products</h3><h1 class='overview-h1-second'> ?/? <p class='overview-p-second'>Online</p> </h1> <div class='module-button' id='configure'> <button type='button' class='btn btn-secondary'></button> <div class='button-animation'></div> <div class='button-content'> <span class='content-text'>Configure</span> </div> </div> </div> </div>`
);
id++;
setOpen(false);
} else if (state !== "" && stateComment === "") {
document
.getElementById("center")
.insertAdjacentHTML(
"beforeend",
`<div class='overview-box' id=${id}> <img class='image' src=${file} alt='placeholder'/> <div class='box-content'><h3 class='overview-h3' id='new-headline'>${state}</h3> <p class='overview-p'>${stateComment}</p><h3 class='overview-h3-second'>Connected Products</h3><h1 class='overview-h1-second'> ?/? <p class='overview-p-second'>Online</p> </h1> <div class='module-button' id='configure'> <button type='button' class='btn btn-secondary'></button> <div class='button-animation'></div> <div class='button-content'> <span class='content-text'>Configure</span> </div> </div> </div> </div>`
);
id++;
setOpen(false);
} else {
alert("Please fill in atleast one value.");
}
};
function openDialog() {
document.getElementById("inputUpload").click();
}
function loadFile(e) {
console.log(e.target.files);
setFile(URL.createObjectURL(e.target.files[0]));
}
document.addEventListener("click", function(e) {
})
name = state;
comment = stateComment;
filename = file;
return (
<React.Fragment>
<div className="modalDark" style={{ paddingRight: "250px" }}>
<div class="modal-dialog">
<div class="modal-content" style={{ width: "800px" }}>
<div class="modal-close">
<div class="module-button" style={{ left: "750px" }}>
<button
class="btn btn-link "
onClick={() => setOpen(false)}
></button>
<div class="button-animation"></div>
<div class="button-content new">
<i class="icon icon-dc_close"></i>
</div>
</div>
</div>
<div class="modal-header">
<h3>Add new Application</h3>
</div>
<div class="modal-body">
<div
class="module-input form-group has-placeholder"
data-plugin="moduleInput"
style={{ bottom: "60px", width: "350px" }}
>
<label for="demo-default">Customer Name</label>
<div class="input-animation-wrapper">
<input
type="text"
id="demo-default"
class="form-control "
value={state}
maxLength="42"
placeholder="[Application Name]"
onChange={(e) => handleChange(e)}
/>
<div class="input-animation"></div>
</div>
</div>
<div
class="module-textarea form-group floating-label has-placeholder"
data-plugin="moduleInput"
style={{ bottom: "60px" }}
>
<label for="demo-3">Customer Short text</label>
<div
class="input-animation-wrapper"
style={{ width: "350px" }}
>
<textarea
id="demo-3"
class="form-control"
rows="9"
placeholder="Short description of Customer; max. 280 characters"
maxLength={180}
value={stateComment}
onChange={(e) => handleComment(e)}
style={{ width: "350px" }}
></textarea>
<div class="label-area"></div>
<div class="input-animation"></div>
</div>
</div>
<img
class="image"
alt="Customer Logo"
id="logo"
src={file}
style={{
left: "420px",
bottom: "280px",
position: "absolute",
height: "250px",
}}
/>
<div
class="module-button"
style={{
left: "500px",
bottom: "200px",
position: "absolute",
zIndex: "1",
}}
>
<button
type="file"
class="btn btn-light"
onClick={() => openDialog()}
id="fileUpload"
>
<input
type="file"
hidden={true}
accept="image/*"
id="inputUpload"
onChange={(e) => loadFile(e)}
></input>
</button>
<div class="button-animation"> </div>
<div class="button-content">
<span class="content-text">Upload Logo</span>
</div>
</div>
<div
class="module-button"
style={{ bottom: "50px", width: "100px", textAlign: "center" }}
>
<button
type="button"
class="btn btn-secondary btn"
onClick={() => addNewApplication()}
id="adding"
></button>
<div class="button-animation"></div>
<div class="button-content">
<span class="content-text">Add</span>
</div>
</div>
</div>
</div>
</div>
</div>
</React.Fragment>
);
};
export default ApplicationModal;
export { name, comment, filename };
ApplicationOverview.js:
import React from "react";
import placeholder from "../icons/placeholder.png";
import ApplicationModal from "../components/ApplicationModal.jsx";
const ApplicationOverview = () => {
const [open, setOpen] = React.useState(false);
return (
<div id="wrapper">
{open && <ApplicationModal setOpen={setOpen} />}
<div class="component-headline">
<h4 style={{ color: "gray", display: "inline" }}>
Application overview
</h4>
<div
class="module-button"
style={{
backgroundColor: "rgb(18,205,212,255)",
borderRadius: "12px",
marginLeft: "1032px",
}}
onClick={() => setOpen(true)}
>
<button type="button" class="btn btn-secondary"></button>
<div class="button-animation"></div>
<div
class="button-content"
style={{
backgroundColor: "rgb(18,205,212,255)",
borderRadius: "12px",
}}
>
<span class="content-text" style={{ color: "black" }}>
Add Application
</span>
</div>
</div>
</div>
<hr style={{ marginTop: "-20px" }} />
<!-- This is where the added content should be appended to, below are three examples -->
<!-- of hardcoded panels that should be normally added through the Modal" -->
<div class="center-content" id="center">
<div class="overview-box">
<img
class="image"
src={placeholder}
alt="placeholder"
/>
<div class="box-content">
<h3 class="overview-h3">Press</h3>
<p class="overview-p">This Application is used for maintenance</p>
<h3 class="overview-h3-second">Connected Products</h3>
<h1 class="overview-h1-second">
?/?
<p class="overview-p-second">Online</p>
</h1>
<div class="module-button" id="configure">
<button type="button" class="btn btn-secondary"></button>
<div class="button-animation"></div>
<div class="button-content">
<span class="content-text">Configure</span>
</div>
</div>
</div>
</div>
<div class="overview-box">
<img
class="image"
src={placeholder}
alt="placeholder"
/>
<div class="box-content">
<h3 class="overview-h3">Tooling Machine</h3>
<p class="overview-p">
This Application is used for drilling records
</p>
<h3 class="overview-h3-second">Connected Products</h3>
<h1 class="overview-h1-second">
?/?
<p class="overview-p-second">Online</p>
</h1>
<div class="module-button" id="configure">
<button type="button" class="btn btn-secondary"></button>
<div class="button-animation"></div>
<div class="button-content">
<span class="content-text">Configure</span>
</div>
</div>
</div>
</div>
<div class="overview-box">
<img
class="image"
src={placeholder}
alt="placeholder"
/>
<div class="box-content">
<h3 class="overview-h3">Storing Unit</h3>
<p class="overview-p">
This Application is used to store parameters
</p>
<h3 class="overview-h3-second">Connected Products</h3>
<h1 class="overview-h1-second">
?/?
<p class="overview-p-second">Online</p>
</h1>
<div class="module-button" id="configure">
<button type="button" class="btn btn-secondary"></button>
<div class="button-animation"></div>
<div class="button-content">
<span class="content-text">Configure</span>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default ApplicationOverview;
Modal Window
ApplicationOverview
You can put your useState in the ApplicationOverview.js and pass them as props to the ApplicationModal. So when the applicationModal set the useState the ApplicationOverview has the data and can simply display it.
in your ApplicationOverview:
const [state, setState] = React.useState("");
const [stateComment, setStateComment] = React.useState(placeholder);
const [file, setFile] = React.useState({placeholder});
return (
<div id="wrapper">
{open && <ApplicationModal setOpen={setOpen} setState={setState} state={state} setFile={setFile} file={file} setStateComment={setStateComment} stateComment={stateComment}/>
rest of your HTML
)
then where you want to display the result in the ApplicationOverview you can:
{state && stateComment { display what you want}}

how to make reactstrap dropdown not close when clicked on?

So basically, I have a functional component that shows a reactstrap dropdown.
Here's how it looks. according to the picture i want to be able to click on the box and the dots show in green (the dropdown box is shown in red) without closing the dropdown (by default, it closes when clicked on).
Right now, I'm using stopImmediatePropagation which is incorrect and throws an error:
Uncaught TypeError: e.stopImmediatePropagation is not a function
But meanwhile preserves the functionality i want (it prevents closing the dropdown which i assume has something to do with not letting event propagate to the parent)
And here's the code, Any insight or solution?
import React from "react"
import { ImAttachment } from "react-icons/im"
import { FiMoreVertical } from "react-icons/fi"
import { DropdownItem, DropdownMenu, DropdownToggle, UncontrolledDropdown } from "reactstrap"
import Avatar from "src/#core/components/avatar"
import { VscTriangleRight } from "react-icons/vsc"
import BpmsIconButton from "src/components/#bpms/Buttons/BpmsIconButton"
const Items = (props) => {
const {
title = "title",
subtitle = "subtitle",
itemAvatar,
color = "",
actions = null,
index = -1
} = props
const stopBubbling = (e) => {
e.stopImmediatePropagation()
}
return (
<DropdownItem tag="div" className="dropdown-item-custom" onClick={stopBubbling}>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex no-pointer">
<div className="d-flex cursor-pointer">
{!/\//.test(itemAvatar) ? ( // string containing / indicates of url
<Avatar
className="rounded"
color={`light-${color}`}
size="lg"
icon={<span>{itemAvatar}</span>}
/>
) : (
<Avatar
className="rounded rounded-circle"
color={color}
size="lg"
icon={<img src={itemAvatar} alt="item" />}
/>
)}
</div>
<div className="text-custom">
<div className="flex-column">{title}</div>
<div className="flex-column text-muted">{subtitle}</div>
</div>
</a>
<UncontrolledDropdown>
<DropdownToggle tag="a">
<span className="dropdown-file-type">
<span className="dropdown-file-type-text">
<BpmsIconButton icon={<FiMoreVertical size={20} />} />
</span>
</span>
</DropdownToggle>
<DropdownMenu className="dropdown-menu-inside-custom">
<DropdownItem tag="div" onClick={() => actions().edit(index)}>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex">
<div className="action-text-custom">ویرایش</div>
</a>
</div>
</div>
</DropdownItem>
<DropdownItem tag="div" onClick={() => actions().remove(index)}>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex">
<div className="action-text-custom">حذف</div>
</a>
</div>
</div>
</DropdownItem>
<DropdownItem tag="div" onClick={() => actions().view(index)}>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex">
<div className="action-text-custom">مشاهده</div>
</a>
</div>
</div>
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</div>
</div>
</DropdownItem>
)
}
const GeneralTab = (props) => {
const { general, items, settings } = props || {}
const {
Icon: HeaderIcon = ImAttachment,
ActionsIcon: MoreIcon = FiMoreVertical,
text = "اسناد و مدارک",
index,
generalActions = null,
itemActions = null
} = general || {}
const { color = "" } = settings || {}
const stopBubbling = (e) => {
e.stopImmediatePropagation()
}
return (
<UncontrolledDropdown>
<DropdownToggle tag="div" className="p-0 general-tab-hover">
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex me-5">
<HeaderIcon size={20} className="title-icons" />
<span>
{`${text}`}
{index && `(${index})`}
</span>
</a>
</div>
</div>
</DropdownToggle>
<DropdownMenu className={`mt-0 dropdown-menu-custom border-top border-${color}`}>
<DropdownItem
key="fixed"
tag="div"
className={`dropdown-item-custom text-${color}`}
onClick={stopBubbling}
>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex no-pointer">
<span className="dropdown-file-type">
<span className="dropdown-file-type-no-height">
<HeaderIcon size={20} className="" />
</span>
</span>
<span className="text-custom">{text}</span>
</a>
<div className="d-flex cursor-pointer">
<UncontrolledDropdown>
<DropdownToggle tag="a">
<span className="dropdown-file-type">
<span className="dropdown-file-type-no-height">
<MoreIcon size={20} />
</span>
</span>
</DropdownToggle>
<DropdownMenu className="dropdown-menu-inside-custom">
<DropdownItem tag="div" onClick={generalActions().newItem}>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex">
<div className="action-text-custom">جدید</div>
</a>
</div>
</div>
</DropdownItem>
<DropdownItem tag="div" onClick={generalActions().downloadAll}>
<div className="text-nowrap">
<div className="d-flex flex-row justify-content-start">
<a className="d-flex">
<div className="action-text-custom">دانلود همه</div>
</a>
</div>
</div>
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</div>
</div>
</div>
</DropdownItem>
<div className="dropdown-scrollbar">
{Array.isArray(items) &&
items.map((item, idx) => (
<Items key={idx} {...item} actions={itemActions} />
))}
</div>
</DropdownMenu>
</UncontrolledDropdown>
)
}
export default GeneralTab

Change boolean value onClick in React

I'm trying to change the value of a boolean from an object imported from a JSON file in React. I want the offers.availability value to change to false after clicking on the "add to cart" button.
Here's my code:
function App() {
class App {
constructor () {
this.state = {
offers: [],
}
this.handleToggle = this.handleToggle.bind(this);
}
componentDidMount() {
this.state.setState({ offers: Data });
}
handleToggle (offers) {
this.setState(prevState => ({
offers: prevState.offers.map(prevOffer => {
if (prevOffer.availability === offers.availability) {
return {
availability: prevOffer.availability,
isTrue: !prevOffer.isTrue
}
}
return prevOffer;
})}));
}
}
return (
<div className="container">
<div className="row">
{Data.offers.map(offers => {
return(
<div key={offers.make + offers.model + offers.engine + offers.photo} className="col-sm-4">
<div className="card" >
<img src={offers.photo} className="card-img-top" alt={offers.make + ' ' + offers.model } width="100%"/>
<div className="card-body pt-0 px-0">
<div className="d-flex flex-row justify-content-between mb-0 px-3 p-3 mid">
<div className="d-flex flex-column">
<h4>{offers.make} {offers.model}</h4>
</div>
<div className="d-flex flex-column">
<button type="button" className="btn btndelete"><FaTrash /></button>
</div>
</div>
<div className="d-flex flex-row justify-content-between px-3">
<div className="d-flex flex-column"><span className="text-muted">Engine: {offers.engine}</span></div>
<div className="d-flex flex-column">
{offers.availability.toString()}
</div>
</div>
<div className="mx-3 mt-3 mb-2 d-grid gap-2">
{offers.availability
? <button type="button" className="btn btn-primary addtocartbtn" onClick={() => Data.offers.handleToggle(offers)}>
<small>Add to cart</small>
</button>
: <button type="button" className="btn btn-disabled" onClick={console.log('???')}><small>Currently unavailabe</small></button>
}
</div>
</div>
</div>
</div>
)
}) }
</div>
</div>
)}
export default App;
I tried to toggle the boolean value but I currently get a ".offers.handleToggle is not a function" error after clicking.
I'm new to this so please don't judge if I did something really stupid here :) What could be the possible solution to this?
You should not use Data.offers.handleToggle. From what I see, Data.offers is an array of objects which they don't have a function handleToggle defined.
However, you are defining a function handleToggle on the App component that looks good. It should work if you change onClick={() => Data.offers.handleToggle(offers)} with either onClick={() => handleToggle(offers)} or onClick={() => this.handleToggle(offers)}
UPDATE
After running your code I saw the component is defined as a mix of a functional component and a class component. First, decide what you are going to use and then fix the errors 1 by 1. The constructor for example is missing the props, there are onclicks that are not well defined and a few more things.
Here is your code if used as a class component.
import { Component } from "react";
export class App extends Component<{}, { offers: any[] }> {
constructor(props: {}) {
super(props);
this.state = {
offers: [],
};
this.handleToggle = this.handleToggle.bind(this);
}
componentDidMount() {
this.setState({ offers: Data });
}
handleToggle(offers: any) {
this.setState((prevState) => ({
offers: prevState.offers.map((prevOffer) => {
if (prevOffer.availability === offers.availability) {
return {
availability: prevOffer.availability,
isTrue: !prevOffer.isTrue,
};
}
return prevOffer;
}),
}));
}
render() {
return (
<div className="container">
<div className="row">
{this.state.offers.map((offers) => {
return (
<div
key={offers.make + offers.model + offers.engine + offers.photo}
className="col-sm-4"
>
<div className="card">
<img
src={offers.photo}
className="card-img-top"
alt={offers.make + " " + offers.model}
width="100%"
/>
<div className="card-body pt-0 px-0">
<div className="d-flex flex-row justify-content-between mb-0 px-3 p-3 mid">
<div className="d-flex flex-column">
<h4>
{offers.make} {offers.model}
</h4>
</div>
<div className="d-flex flex-column">
<button type="button" className="btn btndelete">
<FaTrash />
</button>
</div>
</div>
<div className="d-flex flex-row justify-content-between px-3">
<div className="d-flex flex-column">
<span className="text-muted">
Engine: {offers.engine}
</span>
</div>
<div className="d-flex flex-column">
{offers.availability.toString()}
</div>
</div>
<div className="mx-3 mt-3 mb-2 d-grid gap-2">
{offers.availability ? (
<button
type="button"
className="btn btn-primary addtocartbtn"
onClick={() => this.handleToggle(offers)}
>
<small>Add to cart</small>
</button>
) : (
<button
type="button"
className="btn btn-disabled"
onClick={() => console.log("???")}
>
<small>Currently unavailabe</small>
</button>
)}
</div>
</div>
</div>
</div>
);
})}
</div>
</div>
);
}
}
You just need to define the offers type and a FaTrash component

Filter not working proper in react its working only for first time also how to filter true and false

Here is my code
https://stackblitz.com/edit/react-nsxxqp?file=src%2FApp.js
and my local code is here how to filter i don't know i am new for react and JavaScript please help me i don't know how to finish my task.
import React, { useEffect, useState } from "react";
const Product = (props) => {
const [allButtons, setAllButtons] = useState([]);
const [product, setProduct] = useState([]);
useEffect(() => {
fetch("https://api.spacexdata.com/v3/launches?limit=100")
.then(response => response.json())
.then(productsList => {
setProduct(productsList);
setAllButtons(productsList);
});
}, []);
const onBtnClick = (e) =>{
setProduct(product.filter(i=>i.launch_year == e));
};
return(
<div className="container-fluid">
<div className="row">
<div className="col-xl-12">
<h2>SpacesX Launch Programme</h2>
</div>
</div>
<div className="row">
<div className="col-xl-2 col-lg-2 col-md-2 col-sm-2 col-xs-12">
<div className="inner">
<p className="bold">Filter</p>
<div className="col12 launchYear">
<p className="marg0">Launch Year</p>
{allButtons.map(productYr => (
<button
className="btn btn-primary btnSpacex"
key={productYr.launch_year}
onClick={(e) => onBtnClick(productYr.launch_year)}
>
{productYr.launch_year}
</button>
))}
</div>
<div className="clearfix" />
<div className="col12 launchYear">
<p className="marg0">Successful Launch</p>
<button className="btn btn-default btnSpacex">True</button>
<button className="btn btn-default btnSpacex">False</button>
</div>
<div className="clearfix" />
<div className="col12 launchYear">
<p className="marg0">Successful Landing</p>
<button className="btn btn-default btnSpacex">True</button>
<button className="btn btn-default btnSpacex">False</button>
</div>
</div>
</div>
<div className="col-xl-10 col-lg-10 col-md-10 col-sm-10 col-xs-12 items1">
<div className="row">
{product.map(product => (
<div
key={product.flight_number}
className="col-xl-3 col-lg-3 col-md-3 col-sm-3 col-xs-12 marginBottom15"
>
<div className="inner">
<img
src={product.links.mission_patch}
className="full-width imgBg"
alt={product.mission_name}
/>
<div className="clearfix" />
<p className="productName bold margBot5">
{product.mission_name} #{product.flight_number}
</p>
<div className="clearfix" />
<p className="bold margBot5">
Mission Ids:
<ul className="marg0 blueClr">
<li>{product.mission_id}</li>
</ul>
</p>
<div className="clearfix" />
<p className="bold margBot5">
Launch Year:{" "}
<span className="normal blueClr">
{product.launch_year}
</span>
</p>
<div className="clearfix" />
<p className="bold margBot5">
Successful Launch:{" "}
<span className="normal blueClr">
{product.launch_success}
</span>
</p>
<div className="clearfix" />
<p className="bold margBot5">
Successful Landing:{" "}
<span className="normal blueClr">
{product.rocket.land_success}
</span>
</p>
</div>
</div>
))}
</div>
</div>
</div>
</div>
)
}
export default Product
Main issue here is your onButtonClick function. Change it to the following code (instead of product.filter, use allButtons.filter):
const onBtnClick = e => {
setProduct(allButtons.filter(i => i.launch_year == e));
};
The problem was that you had all of your products, then when you selected the first button, you set the product to just that button. On the next click, you're trying to filter on just the single product that you selected in the first click. To get around this, you want the filter to always be on the allButtons list (I'm assuming this was just a small oversight on your part, it looks like you knew exactly what you were trying to do but just accidentally put the wrong list in the function).
Another small change that I would make to your code is below: (introduce index parameter and use it as the key):
{allButtons.map((productYr, index) => (
<button
className="btn btn-primary btnSpacex"
key={index}
onClick={e => onBtnClick(productYr.launch_year)}
>
{productYr.launch_year}
</button>
))
}
This will eliminate all those console warnings that you're getting for having duplicate keys.
Check below code
import React, { useEffect, useState } from "react";
const Product = (props) => {
const [allButtons, setAllButtons] = useState([]);
const [launchSuccess, launchAllSuccess] = useState([]);
const [landSuccess, landAllSuccess] = useState([]);
const [product, setProduct] = useState([]);
useEffect(() => {
fetch("https://api.spacexdata.com/v3/launches?limit=100")
.then(response => response.json())
.then(productsList => {
setProduct(productsList);
setAllButtons(productsList);
launchAllSuccess(productsList);
landAllSuccess(productsList);
});
}, []);
const onBtnClick = e => {
setProduct(allButtons.filter(i => i.launch_year === e));
};
const onBtnLaunchAllSuccess = e =>{
setProduct(launchSuccess.filter(i => i.launch_success === e));
}
const onBtnLandSuccessful = e =>{
setProduct(landSuccess.filter(i => i.rocket.first_stage.cores[0].land_success === e));
}
return(
<div className="container-fluid">
<div className="row">
<div className="col-xl-12">
<h2>SpacesX Launch Programme</h2>
</div>
</div>
<div className="row">
<div className="col-xl-2 col-lg-2 col-md-2 col-sm-2 col-xs-12">
<div className="inner">
<p className="bold">Filter</p>
<div className="col12 launchYear">
<p className="marg0">Launch Year</p>
{allButtons.map((productYr, index) => (
<button
className="btn btn-primary btnSpacex"
key={index}
onClick={e => onBtnClick(productYr.launch_year)}
>
{productYr.launch_year}
</button>
))
}
</div>
<div className="clearfix" />
<div className="col12 launchYear">
<p className="marg0">Successful Launch</p>
<button
onClick={e => onBtnLaunchAllSuccess(true)}
className="btn btn-default btnSpacex">True</button>
<button
onClick={e => onBtnLaunchAllSuccess(false)}
className="btn btn-default btnSpacex">False</button>
</div>
<div className="clearfix" />
<div className="col12 launchYear">
<p className="marg0">Successful Landing</p>
<button
onClick={e => onBtnLandSuccessful(true)}
className="btn btn-default btnSpacex">True</button>
<button
onClick={e => onBtnLandSuccessful(false)}
className="btn btn-default btnSpacex">False</button>
</div>
</div>
</div>
<div className="col-xl-10 col-lg-10 col-md-10 col-sm-10 col-xs-12 items1">
<div className="row">
{product.map(product => (
<div
key={product.flight_number}
className="col-xl-3 col-lg-3 col-md-3 col-sm-3 col-xs-12 marginBottom15"
>
<div className="inner">
<img
src={product.links.mission_patch}
className="full-width imgBg"
alt={product.mission_name}
/>
<div className="clearfix" />
<p className="productName bold margBot5">
{product.mission_name} #{product.flight_number}
</p>
<div className="clearfix" />
<p className="bold margBot5">
Mission Ids:
<ul className="marg0 blueClr">
<li>{product.mission_id}</li>
</ul>
</p>
<div className="clearfix" />
<p className="bold margBot5">
Launch Year:
<span className="normal blueClr">
{product.launch_year}
</span>
</p>
<div className="clearfix" />
<p className="bold margBot5">
Successful Launch:
<span className="normal blueClr">
{product.launch_success}
</span>
</p>
<div className="clearfix" />
<p className="bold margBot5">
Successful Landing:
<span className="normal blueClr">
{product.rocket.first_stage.cores[0].land_success}
</span>
</p>
</div>
</div>
))}
</div>
</div>
</div>
</div>
)
}
export default Product

Categories

Resources