Non-component onclick trigger React Component update - reactjs

If I have some buttons which were not React components, e.g. for an add to basket:
<button value="1">Buy Product 1</button>
<button value="2">Buy Product 2</button>
<button value="3">Buy Product 3</button>
And I have a React component that stores the values of buttons clicked (e.g. a basket view), how would I get the data from the buttons clicked into the react component? Would an event listener like this for each button suffice?: https://facebook.github.io/react/tips/dom-event-listeners.html) I'm trying to do this all client side, as the buttons wil be rendered server side on pageload.
Thanks in advance!
EDIT:
In response to a suggestion below, here's a bit more background information:
The issue is that the buttons are generated in PHP and aren't repeated one after the other. We have a pre-existing system of twig template'd product listings, so the only real solution is to keep the buttons rendered as is, and use a react component for the basket view. So a click of a pre-existing non-react button needs to pass the value (product sku/id) into the react component to update the basket

You can try something like this :
class App extends Component {
constructor(props) {
this.state = {
basket: []
}
this.addItemToBasket = this.addItemToBasket.bind(this);
}
addItemToBasket(e) {
let item = e.value;
let basket = this.state.basket;
basket.push(item);
this.setState({basket: basket});
}
render() {
return(
<button value="1" onClick={this.addItemToBasket(this)}>Buy Product 1</button>
<button value="2" onClick={this.addItemToBasket(this)}>Buy Product 2</button>
<button value="3" onClick={this.addItemToBasket(this)}>Buy Product 3</button>
<Basket items={this.state.basket} />
}
}
}
this will call addItemToBasket when each button is clicked and then add that item to the basket and set the state with the new basket. Then you can pass the state as a prop to the component where you want to display what is added.

Related

How do I click button to change component in this scenario

Hello, I don't know how to change component when clicking on the button on the left side, so it'll render the component into the right side, but only the one that I want, not all of it, I know how to clicking component, it'll transfer me into another route using Switch, etc but this doesn't seem like the case. Can someone help me out?
I can't figure out how to keep the button at the left side stay while the right side component is changing
Here are my code:
import { Component } from "react";
import UserManagement from "../UserManagement/index";
import RoleManagement from "../RoleManagement/index";
import QuizManagement from "../QuizManagement/index";
class Admin extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div class="admin-section">
<div class="admin-control col-25">
/- 3 buttons for 3 components I want to render
<button>
<label>User management</label>
</button>
<button>
<label>Role management</label>
</button>
<button>
<label>Quiz management</label>
</button>
</div>
<div class="admin-modify col-75">
/- When I click button the component will display here, I just don't know how to parse it into here but only one, if it like this it'll render all 3 of it.
<UserManagement />
<RoleManagement />
<QuizManagement />
</div>
</div>
);
}
}
export default Admin;
A simple solution would be:
Step 1 : Add a state called management in this.state = {}. Like
constructor(props) {
super(props);
// you can default this to any of the three
this.state = {management: "user"};
}
Step 2: Add onClick handler on the buttons like
<button onClick={() => {this.setState({management: "user"}) }}>
<label>User management</label>
</button>
<button onClick={() => {this.setState({management: "role"}) }}>
<label>Role management</label>
</button>
<button onClick={() => {this.setState({management: "quiz"}) }}>
<label>Quize management</label>
</button>
Step 3: Conditionally render your tables based on the state.
{this.state.managment === "user" && <UserManagement />}
{this.state.managment === "role" && <RoleManagement />}
{this.state.managment === "quiz" && <QuizManagement />}
Step 4: Turn up :).
Have you tried to simply hide/show the right component when listening to the user's "onClick" event on the left component?

Need to use react hooks to display a component based on button

So I have multiple components and a list of buttons. When I hit a button, I want to use reacthooks to display the corresponding component in {displayComponent}. I only want one component displaying at a time (so if you hit another button it will replace whatever was there previously).
Can someone tell me where i've gone wrong? This isn't working (it's just displaying all three components and the visibility doesn't change). My idea was to have the component display based on if displayComponent matched it's id.
How can I fix it and is there are more efficient way to accomplish this?
import Component1 from "./components/comp1";
import Component2 from "./components/comp2";
import Component3 from "./components/comp3";
function ComponentSelection() {
let [displayComponent, setDisplayComponent] = useState(null);
return(
<Button onClick={setDisplayComponent = "comp1">Click to display component 1</Button>
<Button onClick={setDisplayComponent = "comp2"}>Click to display component 2</Button>
<Button onClick={setDisplayComponent = "comp3"}>Click to display component 3</Button>
{displayComponent}
<Component1 id='comp1' display={displayComponent === 'comp1'} />
<Component2 id='comp2' display={displayComponent === 'comp2'} />
<Component3 id='comp3' display={displayComponent === 'comp3'} />
)
}
export default ComponentSelection
You misunderstood what hooks are. The second element in the returned array is a function to set it. Try this instead:
<Button onClick={() => setDisplayComponent("comp1")}>Click to display component 1</Button>

How to open Materialize confirmation modal when deleting something from a database

Currently, I have a view which shows all documents from the database.
Each one has a button which triggers the document to be deleted from the database.
Ideally, I'd like to open a modal message (using Materialize) to ensure deletion should happen.
I know that I can have a modal for each of the elements but that seems redundant and too much to add. I'd like the flow to go from:
button -> delete
to:
button -> confirm -> delete
I'd like this to happen by changing the onClick of the button to open a modal and be able to pass the action of the confirm button through
The button code currently looks like:
<button
className="btn"
onClick={() => {handleClick(category._id);}}
>
Delete
</button>
The current onClick handler for each button is the following:
const handleClick = id => {
this.props.deleteCategory(id);
};
I'm new to React/Redux and Materialize so any help would be appreciated and if any more information is required, please let me know :)
Thanks,
James
Okay, so I found the solution myself and since I couldn't find much else online on how to do this, I thought I'd share the solution too.
So, I installed react-materialize first and created a component to hold the modal and render the modal.
I replaced the button click function with a function which updates the state of the current component like so:
const handleClick = category => {
this.setState({
categoryClicked: category,
modalOpen: true
});
};
I then tied the component containing the model to this state using props like so:
<ConfirmDeletion
onClickYes={null}
onClickNo={null}
name={this.state.categoryClicked.name}
open={this.state.modalOpen}
actions={[
<button
onClick={modalNo}
className="modal-close waves-effect waves-green btn-flat"
>
No
</button>,
<button
onClick={modalYes}
className="modal-close waves-effect waves-green btn-flat"
>
Yes
</button>
]}
/>
Note that the actions are a list of JSX elements which should be the buttons on the modal.
I also created the click event handlers to update the state (and remove from the database in the "yes" case) as follows:
const modalYes = () => {
this.props.deleteCategory(this.state.categoryClicked._id);
this.setState({
modalOpen: false
});
};
const modalNo = () => {
this.setState({
modalOpen: false
});
};
and just for completeness, here's the component wrapping the modal in case it's useful to anyone in the future:
import React, { Component } from "react";
import { Modal } from "react-materialize";
class ConfirmDeletion extends Component {
render() {
const { name, open, actions } = this.props;
return (
<Modal
id="confirmDeletion"
open={open}
actions={actions}
header="Are you sure?"
>
<div className="modal-content">
<p>
Are you sure you want to do delete '{name}'? It cannot be undone.
</p>
</div>
</Modal>
);
}
}
export default ConfirmDeletion;
Based on Materialize Documentation you should follow these steps :
1- Create your modal structure. for example :
<!-- Modal Structure -->
<div id="modal1" class="modal">
<div class="modal-content">
<h4>Modal Header</h4>
<p>A bunch of text</p>
</div>
<div class="modal-footer">
Agree
</div>
</div>
2- Initialize the modal :
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems, options);
});
Note: remove options if you don't want to add modal options. If don't it causes an error.
3- Change handleClick function to open modal :
const handleClick => {
//var elem = get modal element here
var instance = M.Modal.getInstance(elem);
instance.open();
};
4- Finally, call a function when user click on agree to delete the category. You can add disagree button to close modal with :
instance.close();

Onclick an element that changes the state of another element

I'm trying to click on a sort icon that will trigger to change the order of a list.
To make it more simpler, let's say you have a button and another button and they are on separate divs from each other.
<div>
//Button 1
<button onclick={"some_click_handler"}>
</div>
<div>
//Button 2
<button>
{this.state.someToggle ? true : false}
</button>
</div>
Create a component which passes a callback to the button, this callback will update the state of the container which will in turn set the props of the list. This is very common in React and is the basis of how the compositional pattern works. If you need to share data between two components just put them in a container and lift the state to the parent component. These components are usually called containers and there is a bunch of documentation on it.
This is a good starting point: https://reactjs.org/docs/lifting-state-up.html
Something like this...
class Container extends React.Component {
constructor(props) {
super(props);
// Don't forget to bind the handler to the correct context
this.handleClick = this.handleClick.bind(this);
}
handleClick(sort) {
this.setState({sort: sort});
}
render() {
return (
<Button handleClick={this.handleClick} />
<List sort={this.state.sort} />
)
}
}

Need to add class dynamically to a <Button> in react bootstrap or just react

here is my code in react and bootstrap:
<ButtonGroup>
<Button value=1 onClick={this.props.filterMessages}>In</Button>
<Button value=2 onClick={this.props.filterMessages}>Out</Button>
</ButtonGroup>
When the Button is clicked, I'd like to add a css class called active=True and bsStyle="primary"
function onClick(event) {
/*add CSS class to my Button component, but how?*/
}
Thank you!
You can make it with state of parent component.
function onClick(event) {
this.setState({condition: true})
}
<Button value=1 onClick={this.props.filterMessages} className={this.state.condition? "class" : "anotherClass"}>In</Button>
Create variable, that will keep condition of your button, and change it with some event. In button set className depend of your current value of variable.

Resources