I am having an issue where I want an alert to popup when I click on an image with React. Unfortunately I cannot figure out why this does not work on when I click on the image. Can someone please help me with this issue?
state = {
cards
}
handleClick = () => {
alert("I have been clicked");
console.log("clicked")
}
render = () => {
return (
<Router>
<div className="App">
<Navbar />
<ImageContainer>
{this.state.cards.map(card => {
return <ImageCard handleClick = {this.handleClick} image={card.image} />
})};
</ImageContainer>
</div>
</Router>
);
}
}
Here is what I have for ImageCard:
export const ImageCard = (props) => (
<Col lg={4}>
<Card>
<Card.Img variant="top" src={props.image} />
</Card>
</Col>
);
You are passing a prop called handleClick to your <ImageCard /> component. Take a look at your <ImageCard />. Once it receives that prop it does nothing with it so it is not being used for an onClick in any way. Try renaming the prop from handelClick to onClick, or pass the handeClick down to the <Card /> or <Col /> component within <ImageCard />.
Related
component is like:
<Button and <Icon are customized components which wrap up the <button and <icon
const handleToggleShow = useCallback(() => {
setShow(!show);
}, [show]);
const displayUI = (
<div>
<Icon
testId="editIcon"
onClick={handleToggleShow}
className="edit-icon"
>
</div>
);
const editUI = (
<form data-testid="form" onSubmit={handleSubmit}
<InputComponent />
<Button
testId="saveButton"
text="Save"
disabled={...}
size="large"
color="blue"
type="submit"
/>
<Button
testId="cancelButton"
text="Cancel"
disabled={...}
size="large"
color="grey"
onClick={handleClickCancel}
/>
</form>
);
return(
<div>
{show ? editUI}
{!show? displayUI}
</div>
);
Test is like:
test("show render edit ui when click button", () => {
render(<A {...props} />)
const icon = screen.getByTestId("editIcon");
expect(icon).toBeInDocument();
fireEvent.click(element);
const form = screen.getByTestId("form");
//here throws error: unable to find an element by [data-testid="form"]
expect(form).toBeInDocument();
});
Then I tried queryByTestId("form") and tried getByTestId("saveButton"), it throws error "received value must be an HTMLElement or as an SVGElement",
I was thinking maybe icon click event was not triggered, then I ran this test, still got error
test("show render edit ui when click button", () => {
const handleToggleShow = jest.fn();
render(<A {...props} />)
const icon = screen.getByTestId("editIcon");
expect(icon).toBeInDocument();
fireEvent.click(element);
expect(handleToggleShow).toHaveBeenCalled(); //received number of calls 0
});
Anyone can help? why getByTestId or queryByTestId is not working
Update here:
In the previous test, I didn't pass any mock props to the component.
after passing props, the issue somehow fixed.
Created RenderCard component which creates multiple cards for given data.
I am creating bulk selection of card means selecting multiple cards. So when user click on circle present at the top left then that circle become check circle
So here the issue is that all card gets selected when user click on any card. So I want only that card select which users click
const Card = () => {
const [cardSelect, setCardSelect] = useState(false)
const onMouseEnter = () => {
console.log("onMouseEnter1")
}
const onMouseLeave = () => {
console.log("onMouseLeave1")
}
const logMessage = () => {
setCardSelect(prevCheck => !prevCheck);
}
const RenderCard = () => {
return album.map(item => {
return (
<Col className='container' onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} key={item.title} md='2'>
<Card>
<div>
<Link to={`/pages/blog/detail/${item.id}`}>
<CardImg className='img-fluid image' src={item.img} alt={item.title} top />
</Link>
</div>
<div className='select-card'>
{cardSelect ? <CheckCircle onClick={logMessage} /> : <Circle onClick={logMessage} />}
</div>
<CardBody>
<CardTitle className="image2 te" >
<b>{item.title}</b>
</CardTitle>
<CardText>{item.comment} Comments</CardText>
</CardBody>
</Card>
</Col>
)
})
}
return (
<>
<Row>
<RenderCard />
</Row>
</>
)
}
Anyone can point me in the right direction where I am doing mistakes.
Thanks
If i understand you correctly i would suggest that
you should wrap anything that is inside the return statement and refactor it to its own component, and then pass item as prop in that component and make the clickhandler inside that component. like this:
const RenderCard = () => {
return album.map(item => {
return ( <Component item={item} />)
}
Now the component have its own state that shows either its clicked or not clicked
With this line of code :
cardSelect ? <CheckCircle onClick={logMessage} /> : <Circle onClick={logMessage} />
You are saying : "If cardSelect is true, then render CheckCircle component, otherwise, render Circle component and do that for all items in album list". So when the state changes, it will render only one type of object CheckCircles, or Circles as many times as there are elements in the album list for which you are calling the map method.
That is why you are seeing all checked circles when you set your variable cardSelect to true.
This question already has answers here:
React Conditional Rendering
(4 answers)
Closed 1 year ago.
This is one of the component
const [mic, setMic] = useState(false)
const micClick = () => {
setMic(true)
alert('micClicked',mic)
}
<VideoControls
micClick={micClick}
/>
this is other component
const VideoControls = ({
micClick,
}) => {
return (
<Card style={style} className={classes.root}>
<Button>
<MicIcon style={iconStyle} onClick={micClick} />
</Button>
<Button>
<MicOffIcon style={iconStyle} onClick={micClick} />
</Button>
}
I want to show the MicIcon as a default whenever button is clicked i want to change it as MicOffIcon , but here i dont have any idea how to utilize it. please help me thanks in advance
Since you have a mic state you can pass it down and then based on that state render whatever icon you feel like, as example:
const [mic, setMic] = useState(false)
const micClick = () => {
setMic(true)
alert('micClicked',mic)
}
<VideoControls
micClick={micClick}
mic={mic}
/>
and then inside your VideoControls component:
const VideoControls = ({
micClick,
mic
}) => {
return (
<Card style={style} className={classes.root}>
<Button>
{mic ?
<MicIcon style={iconStyle} onClick={micClick} /> :
<YourOtherIcon/> }
</Button>
<Button>
<MicOffIcon style={iconStyle} onClick={micClick} />
</Button>
}
<VideoControls
micClick={micClick}
mic={mic}
/>
Pass mic as a prop to your VideoControls component. And set your icons according to the value of mic.
const [mic, setMic] = useState(false)
const micClick = () => {
setMic(mic => !mic); // change the value of mic
alert('micClicked',!mic)
}
<VideoControls
micClick={micClick}
mic={mic}
/>
VideoControls Component
const VideoControls = ({
micClick, mic
}) => {
return (
<Card style={style} className={classes.root}>
{mic ?
<Button>
<MicIcon style={iconStyle} onClick={micClick} />
</Button>
:
<Button>
<MicOffIcon style={iconStyle} onClick={micClick} />
</Button>
}
}
You could pass your mic state variable to the VideoControls component and display the relevant Icon based on its value:
<VideoControls
micClick={micClick}
mic={mic}
/>
and
const VideoControls = ({
micClick,
mic
}) => {
return (
<Card style={style} className={classes.root}>
<Button>
{mic ?
<MicIcon style={iconStyle} onClick={micClick} /> :
<MicOffIcon style={iconStyle} onClick={micClick} />
}
</Button>
</Card>
);
I'm trying to find proper way to write the TableWrapper component. I want to be structured something like this when using it. Could you please help me how to pass the props from the parent to the children?
<TableWrapper
loadData={loadData}
data={data}
isExternalOpen={isExternalOpen}
setIsExternalCreate={setIsExternalCreate}
setIsExternalOpen={setIsExternalOpen}
showEmptyState={false}
limit={4}
loading={loading}
>
{({ dispatchHandler, isOpen, setIsOpen, data, previousPage, nextPage }: TableWrapperComponentInterface) => (
<>
<Table
title={title}
onCreateHandler={onCreateHandler}
columns={columns}
data={data}
previousPage={previousPage}
nextPage={nextPage}
actions={[actions]}
/>
<TableModal isOpen={isOpen} setIsOpen={setIsOpen} setIsCreate={setIsCreate}>
<>Doesn't matter</>
</TableModal>
</>
)}
</TableWrapper>
I have something like this but that doesn't seem right. I would be glad if somebody could help me. :)
export const TableWrapper = (props: TableWrapperInterface) => {
const {
children,
loadData,
setIsExternalCreate,
setIsExternalOpen,
emptyStateAddButtonTitle,
emptyStateButton = true,
emptyStateText,
showEmptyState,
loading,
data,
limit = 10,
isExternalOpen,
} = props
...
const Component = children
return (
<>
<div>
<Component
dispatchHandler={dispatchHandler}
setIsOpen={setIsExternalOpen}
isOpen={isExternalOpen}
data={sendData}
loadData={loadData}
previousPage={previousPage}
nextPage={nextPage}
/>
</div>
</>
)
}
export default TableWrapper
I am new in react, i am trying to get component based on if button is clicked and once the component is returned to Ui, i want to change button state back to original(false),so if i click on that button again i should get again new component below to the previous one,and this should just go on..,
in below code i am able to get this just one time.
const Command = () => {
const [buttonState, setButtonState] = useState(false);
const AndOrHandler = () => {
if (buttonState) {
return (
<div>
<Grid container>
<SomeComponent />
</Grid>
</div>
);
}
return null;
};
return (
<Fragment>
<FormControl>
<SomeComponent />
<AndOrHandler />
<Button onClick={() => setButtonState(true)} variant="contained" color="primary">Add Condition</Button>
</FormControl>
</Fragment>
);
};
export default Command;
You want continue adding component, i suggest have state components:
const Command = () => {
const component = <div>
<Grid container>
<SomeComponent />
</Grid>
</div>;
const [components, setComponents] = useState([]);
return (
<Fragment>
<FormControl>
<SomeComponent />
{components.map(component => component)}
<Button onClick={() => setComponents([...components, component])} variant="contained" color="primary">Add Condition</Button>
</FormControl>
</Fragment>
);
};
export default Command;