React JS - Prevent Parent onClick when clicked on child onClick - javascript

Here is the jsx
When i click the ROW myParentClick is triggered but when i click on any child which is myChildClick myChildClick2
Then it triggers both the parent and child.
The Parent is triggered first and then the child
{myData?.map((item, index) => {
return(
<Row onClick={() => myParentClick(index)}>
<Col>
// some html tags
</Col>
<Col>
// some html tags
</Col>
<Col>
// React Bootstrap DropDown
<DropDown>
<DropDown.Toggle>
// code
</DropDown.Toggle>
<DropDown.Menu>
<DropDown.Item onClick={() => myChildClick(index)}>
<p>some TEXT</p>
</DropDown.Item>
</DropDown.Menu>
</DropDown>
</Col>
<Col onClick={() => myChildClick2(index)} >
<p>some TEXT</p>
</Col>
<Col onClick={() => myChildClick3(index)} >
<p>some TEXT</p>
</Col>
</Row>
)
})}
I have tried, on child click e.stopPropagation(); which is not working
onClick={
(e) => {
e.stopPropagation();
myChildClick(index)
}
}
How to Prevent Parent onClick when clicked on child onClick ?

Try
onClick={
(e) => {
if (e.defaultPrevented) return
e.preventDefault()
myChildClick(index)
}
}

i took your code and tried to reproduce your issue. for some reason your stopPropagation doesnt work for you, but when i tried it, it works fine:
https://stackblitz.com/edit/react-ts-mk1dcr

Related

Adding and removing (toggle) active class on React

I am changing the state with onClick and adding a border to the data of that state name. But when I click the other boxes, the previously added border is not removing. Here is my code;
const [toggleState, setToggleState] = useState(null);
return (
<React.Fragment>
<Col sm="6">
<Card className="text-center">
<CardBody onClick={() => setToggleState(user.name)} className={toggleState === user.name ? 'selectedItem' : '' + ' cursorPointer'} >
<Row onClick={event => props.onChange('true')}>
<Col sm="4">
</Col>
</Row>
</CardBody>
</Card
</Col>
</React.Fragment>
Hard to say what the className you're looking to set is, but Unmitigated seems to have a good idea about that issue. I also noticed that you don't close your
</Card
correctly on the third row from the bottom, this might affect how the page behaves as well.

Getting the value of selected item in Dropdown react-bootstrap

I want to get the value of selected item in Dropdown. I uses react-bootstrap. I tried placing onSelect={(e) => console.log(e)} at <Dropdown>, <Dropdown.Menu> and <Dropdown.Item> but on selecting one country all of above gives me null.
Dropdown and items are rendered correctly.
please help.
return (
<div>
<FormGroup className={styles.formControl}>
<Dropdown >
<Dropdown.Toggle variant="success" id="dropdown-basic">
Select a Country
</Dropdown.Toggle>
<Dropdown.Menu onSelect={(e) => console.log(e) } className={styles.dropdown_menu}>
{countries.map((country,i) => <Dropdown.Item key={i}>{country}</Dropdown.Item> )}
</Dropdown.Menu>
</Dropdown>
</FormGroup>
</div>
)
const [selectedItem, setSelectedItem] = useState(null);
return (
<div>
<FormGroup className={styles.formControl}>
<Dropdown >
<Dropdown.Toggle variant="success" id="dropdown-basic">
{selectedItem?selectedItem:"Select a country"}
</Dropdown.Toggle>
<Dropdown.Menu className={styles.dropdown_menu}>
{countries.map((country, i) => <Dropdown.Item onSelect={()=>setSelectedItem(country)} key={i}>{country}</Dropdown.Item> )}
</Dropdown.Menu>
</Dropdown>
</FormGroup>
</div>
)
I hope onSelect is the correct handler for the component. Just cross verify that. This should work I suppose.
useState(null) can also be useState(props.value) in case you're passing down something from parent. That's up to you.

Array map function renders correct but calls function with last element rendered

I am using the map function to iterate through a JSON Array which looks similar to this
table=[
{"name":"jon snow",
"house":"stark"
},
{
"name":"arya",
"house":"stark"
},
{"name":"cersei",
"house":"lannister"
}
]
Map function renders the items perfectly however, the onClick handler seems to pass only the last item of the array.
For example, the text items are rendered to display the appropriate name, however, on clicking their individual action button seems to pass only the last element.
Here, after triggering the event handler "handleClose", I logged the "item" element printed to the console but it displays element with name "cersei" even on clicking the element with name "jon snow".
The syntax seems to be fine for the event handler for React afaik. And, since the variable "item" is also local variable within the function. It shouldn't display the last item in the array. Is there anything I am missing over here?
{/*Event Handler*/}
function handleClose(item) {
console.log(item)
setAnchorEl(null);
}
{/*Few lines of code after in the return function of React*/}
var table2=[
{"name":"jon snow",
"house":"stark"
},
{"name":"arya",
"house":"stark"
},
{"name":"cersei",
"house":"lannister"
}
]
console.log(table);
return(
<div>
<div>
</div>
{/*Actual table data*/}
<div>
<Card style={{width:'100%'}}>
<Card.Body>
<div >
{table2.map((item,index)=>{
let tempElement =item;
return(
<div >
<Grid container spacing={0}>
<Grid item xs={2} >
<div style={{backgroundColor:'#fff'}}>
<ListItem alignItems="flex-start">
<ListItemAvatar>
<Avatar src={item.picture} />
</ListItemAvatar>
<ListItemText style={{wordBreak:'normal'}}
primary={item.name}
secondary={
<React.Fragment>
<Typography
component="span"
variant="body2"
className={classes.inline}
color="textPrimary"
>
{getRoleFromData(item.roles)}
</Typography>
</React.Fragment>
}
/>
</ListItem>
</div>
</Grid>
{/*View/Edit buttons */}
<Grid item xs style={{backgroundColor:'#fff'}} >
<div>
<Button aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>Action</Button>
<ThemeProvider>
<Menu
id="simple-menu"
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem><Button onClick={()=>handleClose(item)}>View</Button></MenuItem>
<MenuItem><Button onClick={()=>handleClose(item)}>Edit</Button></MenuItem>
</Menu>
</ThemeProvider>
</div>
</Grid>
</Grid>
<div>
<Divider variant="inset"/>
</div>
</div>
);
})
}
</div>
</Card.Body>
</Card>
</div>
</div>

Click events are not available on the map of the react

{userList.map(v => (
<Card
key={v.user}
onClick={() =>
console.log("object")
}
>
<Card.Header
title={v.user}
thumb={require(`../img/${v[tableName].avatar}.png`)}
extra={<span>{v[tableName][extra]}</span>}
/>
<Card.Body>
{v[tableName].desc.split(/\n/g).map((v, k) => (
<li key={k}>{v}</li>
))}
</Card.Body>
</Card>
))}
Click events are not available on the .map() function in React
Card Component of React material UI does not support onClick props so you should not use it.
Quick Fix would be to enclose it inside a div and add onClick on the div as shown below:
<div onClick=> {() =>
console.log("object")
}>
<Card>
.....
</Card>
</div>
Or You can use some different library from :
https://material-ui.com/api/card-action-area/

How to replace one React Component with another OnClick?

I have a "sign up" button. When it is clicked, I would like for it to render a new component, called "SignUp". I would like for the new component to replace the "sign up" button.
Currently, I am using setState so that when the button is clicked, a new component is rendered. However, the button is not being replaced, the "SignUp" component is just rendered beside the button. What may be a good approach for me to replace the button with the new component being rendered?
I have provided my code below:
export default class SignUpSignIn extends Component {
constructor() {
super();
this.state = {
clicked: false
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
clicked: true
});
}
render () {
return (
<div id="SignUpSignInDiv">
<Col md="12" sm="12" xs="12" className="text-center">
<div onClick={this.handleClick}>
{this.state.clicked ? <SignUp /> : null}
<Button id="SignUpButton" color="primary"> Sign Up </Button>
</div>
</Col>
</div>
)
}
}
Well, you're not rendering both components conditionally, only the SignUp. Instead of having null in your ternary, render the sign in button when state.clicked === false:
render () {
return (
<div id="SignUpSignInDiv">
<Col md="12" sm="12" xs="12" className="text-center">
{this.state.clicked ? (
<SignUp />
) : (
<Button id="SignUpButton" color="primary" onClick={this.handleClick}> Sign Up </Button>
)}
</Col>
</div>
)
}
one way to do it is like this , i didnt test it yet but it should work
render () {
let show = <div></div>
if(this.state.clicked){
show = <SignUp />
}
return (
<div id="SignUpSignInDiv">
<Col md="12" sm="12" xs="12" className="text-center">
{show}
<Button id="SignUpButton" color="primary" onClick={this.handleClick}> Sign Up </Button>
</Col>
</div>
)
}

Categories