React Js How to Trigger an Event to Another Div

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

  1. In React CollectionItem component use mapStateToProps so you'll get cartItems as a props from the STORE.
  2. Rewrite function triggered onClick event so it do all necessary changes with cartItems and then return updated cartItems list in action.
  3. 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



Leave a reply



Submit