react.js trigger event inside another component upon button click
In React, data can only be passed down from parent to child via props (see note at the end for more detail on this), not from sibling to sibling. This doesn't mean, however, that siblings cannot cause updates in each other, it just means that you need to restructure your code a bit so that data flows down properly.
You can store the active chatroom ID in the parent of the list and detail views and let the list view update the ID while the detail view uses the ID to load messages.
Here's a simple example:
function Chat() {
const [activeRoomID, setActiveRoomID] = React.useState(null);
const onActiveChange = React.useCallback((id) => {
setActiveRoomID(id);
}, []);
return (
<div>
<ChatRoomList onActiveChange={onActiveChange}/>
<ChatMessages id={activeRoomID}/>
</div>
)
}
function ChatRoomList({ onActiveChange }) {
// ...
return (
<div>
{chatRooms.map(chatRoom => (
<div key={chatRoom.chatIDFromTableChats}>
<div>ChatroomID: {chatRoom.chatIDFromTableChats}</div>
<Button onClick={() => onActiveChange(chatRoom.chatIDFromTableChats)}>Open</Button>
</div>
))}
</div>
)
}
function ChatMessages({ id }) {
// load messages for `id` and display
}
Notice that the data only flows down from the <Chat>
component to its children.
Note about data only flowing from parent to child: There are additional complexities to this statement. As this example shows, children can also pass data up to their parents but only by using a callback function provided via props, so the React-specific parts still only allow data to flow down. Also the context API allows for passing data to deep descendants (not just children).
React JS pass click event to another component
You don't need to pass the click event around, you just need to move the anchorEl
state to your component with AppBar
and pass anchorEl
and onClose
to DropDownMenu
as props:
function MainAppBar() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
<AppBar position="sticky" className={classes.navBarStyle}>
<Toolbar>
<Avatar alt="" className={classes.userAvatar} src="./avatar.jpg" onClick={handleClick} />
<DropDownMenu anchorEl={anchorEl} onClose={handleClose} />
</Toolbar>
</AppBar>
}
function DropDownMenu({ anchorEl, onClose }) {
const open = Boolean(anchorEl);
return (
<div>
<Menu
id="fade-menu"
anchorEl={anchorEl}
keepMounted
open={open}
onClose={onClose}
TransitionComponent={Fade}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</div>
);
}
I wrote a library, material-ui-popup-state
, that is less cumbersome to use for cases like this:
import {bindTrigger, bindMenu, usePopupState} from 'material-ui-popup-state/hooks';
function MainAppBar() {
const popupState = usePopupState({ variant: 'popover', popupId: 'fade-menu' });
<AppBar position="sticky" className={classes.navBarStyle}>
<Toolbar>
<Avatar {...bindTrigger(popupState)} alt="" className={classes.userAvatar} src="./avatar.jpg" />
<DropDownMenu popupState={popupState} />
</Toolbar>
</AppBar>
}
function DropDownMenu({ popupState }) {
return (
<div>
<Menu
{...bindMenu(popupState)}
keepMounted
TransitionComponent={Fade}
>
<MenuItem onClick={popupState.close}>Profile</MenuItem>
<MenuItem onClick={popupState.close}>My account</MenuItem>
<MenuItem onClick={popupState.close}>Logout</MenuItem>
</Menu>
</div>
);
}
How do I trigger a click event based on a specific className in ReactJS
I see two possible ways:
- instead of addItem(), create two separated functions where for 0,5kg onClick action only item.price will be in use and second function for 1kg where you use item.price2
or
- add second parameter to the addItem() function so it will be possible to differ which price you should use in particular action, like:
const addItem = (item, priceType) => {
switch (priceType) {
case 'price':
// 0,5kg
case 'price2':
// 1kg
default: //default case
}
}
...
<div>
<CustomButton
...
onClick={() => addItem(item, 'price')}
>
Add 1/2kg
</ CustomButton>
<CustomButton
...
onClick={() => addItem(item, 'price2')}
>
Add 1kg
</ CustomButton>
</div>
REDUX
I suggest you to use method no.1 without anti pattern. I have also added method no.2 where I keep the original author way of thinking.
METHOD 1. WITHOUT ANTI PATTERN
- In React
CollectionItem
component use mapStateToProps so you'll getcartItems
as a props from the STORE. - Rewrite function triggered onClick event so it do all necessary changes with cartItems and then return updated cartItems list in action.
- Reducer just take updated argument and pass it down to the STORE, without any mutations.
const CollectionItem = ({ item, addItem, cartItems }) => {
const { name, price, price2, imageUrl } = item;
const addItemToList = (item, priceType) => {
// addItemToCart() logic
// cartItems argument is available as a props from STORE
addItem(updatedCartItems); //call action
}
return (
...
<CustomButton
...
onClick={() => addItemToList(item, 'price')}
>
Add 1/2kg
</ CustomButton>
)
}
const mapStateToProps = (state) => ({
cartItems: state.cartItems
});
const mapDispatchToProps = (dispatch) => ({
addItem: (updatedCartItems) => dispatch(addItem(updatedCartItems)),
});
export default connect(mapStateToProps, mapDispatchToProps)(CollectionItem);
Action creator
export const addItem = (updatedItems) => ({
type: CartActionTypes.ADD_ITEMS,
payload: updatedItems,
});
Reducer
case CartActionTypes.ADD_ITEMS:
return {
...state,
cartItems: action.payload, // PURE REDUCER
};
METHOD 2. ANTI PATTERN in reducer
As you updated addItem(item, 'price')
so it receives two parameters, now it's time to update your action creator and reducer so it will be able to accept second parameter 'price'
or 'price2'
.
Action Creator - added priceType
export const addItem = (item, priceType) => ({
type: CartActionTypes.ADD_ITEMS,
payload: item,
priceType
});
Reducer - pass down the priceType
CAUTION! Using addItemToCart()
inside reducer is anti pattern. According to the redux documentation you should never mutate arguments inside reducer, it should stay pure.
case CartActionTypes.ADD_ITEMS:
return {
...state,
cartItems: addItemToCart(state.cartItems, action.payload, action.priceType),
};
Then addItemToCart(cartItems, cartItemToAdd, priceType)
can use switch(priceType)
so it will differ price type.
Trigger a click on a different element when clicking an other div
You can use "refs" to refer to nodes inside a component and trigger things on them.
FileBox = React.createClass({
_handleClick: function(e) {
var inputField = this.refs.fileField;
inputField.click()
},
render: function() {
return <div id="test" onClick={this._handleClick}>
<input ref="fileField" type="file" name="image1" accept=".jpg,.jpeg,.png" id="img1" />
<div id="uploadPhotoButtonText">
+Add Photo 1
</div>
</div>
}
})
Read more about refs here: https://facebook.github.io/react/docs/more-about-refs.html
Trigger event on an injected element in the DOM in React
I believe we have found a solution to this:
useEffect(() => {
let btns = document.getElementsByClassName("class_of_element");
if(btns && btns.length){
btns[0].addEventListener("click", handleClick);
}
});
const handleClick = () => {
console.log("working")
}
Related Topics
Display Data Label (Legend) in Line-Chart Using Chartjs
How to Get a File() or Blob() from an Url in JavaScript
Form Builder - Cannot Read Property 'Get' of Undefined, Issue With Validators
How to Insert Space Every 4 Characters for Iban Registering
Create Parent and Child Relationship Using Lodash
How to Get Multiple Comma Separated Values from Url
React - Clearing an Input Value After Form Submit
Matching a Forward Slash With a Regex
How to Convert Postgresql Time Without Time Zone to Date in JavaScript
How to Fix: Typeerror: Document.Queryselector(...) Is Null
Jquery Remove Special Characters from String and More
React-Select:Get Default Value in React-Select
Special Character Validation Using JavaScript
How to Check If Element Has Focused Child Using JavaScript
Hide Options in Select2 Multi Select