so i have a component that maps an array and returns a div with an onClick event
{credits?.crew.slice(0, maxCreditsResults).map((crew, idx) => {
return (
<div
className='cast-card'
key={idx}
onClick={() => navigate(`/${EPages.person}/${crew.id}`)}
>
<p>-{crew.name}</p>
<p>Department: {crew.department}</p>
</div>
);
})}
i want to test this click event but i dont know how to get that specific div so i can click it with userEvent.click()
i looked at the methods of the sreen that comes from react testing library but i cant find one that would help me
You can add data-testid like <div data-testid = {idx + '-cast-card' }
Then call first element of div.
const element = screen.getByTestId('0-cast-cart')
fireEvent.click(element);
Related
I want to build form in Which there are some text fields as shown in picture
in this form there is a button and after clicking the Add Units button a new form will appear
how can i render this sub form by using button onClick Event-Handler and i also want to render it as many times as i click the button , if i click button one time then it shows the the sub form only one time if i click the button two times then it will show two times
-The main issue is I want the sub form to appear as many time i click the button
(optional if i want to remove the rendered sub form using a button click then please mention the code )
use of react hooks is preferable
you can ask me anything related to question
Here is an example of how to solve your problem. You don't need useEffect, and you don't need three separate state variables. You just need one array of objects.
import React, { useState } from "react";
import ContainerSlot from "./ContainerSlot";
function ReceiptContainer() {
const [containers, setContainers] = useState([]);
const handleAddContainer = () => {
// adding an empty object; you will likely need to
// initialize this object with whatever values are stored
// in the container form
setContainers((current) => [...current, {}]);
};
const handleRemove = (index) => {
const current = [...containers];
current.splice(index, 1);
setContainers(current);
};
return (
<div className="receiptContainer container">
{/* Heading */}
<div className="receiptContainer__heading mt-3">
<h4>Container Invoice</h4>
<hr />
</div>
<button onClick={handleAddContainer}>Add container</button>
<div className="receiptContainer__container">
{/* You will likely need to pass whatever values are in
the container to your ContainerSlot component */}
{containers.map((container, index) => {
const handleRemoveClick = () => {
handleRemove(index);
};
return (
<div
key={`container-${index}`}
style={{ display: "flex", alignItems: "center" }}
>
<div>
<ContainerSlot {...container} />
</div>
<div>
<button onClick={handleRemoveClick}>Remove</button>
</div>
</div>
);
})}
</div>
</div>
);
}
export default ReceiptContainer;
EDIT: updated to show how to remove an item
So I have this modal that is wrapped with an entire background div. My issue is that I added a close function on the background, so no matter where I click, it will close the modal.
I would like to have the useRef only target the background div and not work if I click any of the children inside of it
Here is the code
const modalRef = useRef();
const closeModal = e => {
if (modalRef.current.contains(e.target)) {
setShowModal(false);
}
}
return (
<>
{showModal ? (
<Background onClick={closeModal} ref={modalRef}>
<animated.div style={animation}>
<ModalWrapper showModal={showModal}>
<div>hi</div>
<CloseModalButton
aria-label='Close modal'
// onClick={() => setShowModal(!showModal)}
/>
</ModalWrapper>
</animated.div>
</Background>
) : null}
</>
);
};
So right now the ref is attached to the background, but if I console.log(modalRef.current) it will show me the entire jsx with all my children divs inside, but I only want to target the outside div aka the background
So whenever I click outside of my modal it will close
Note: when I console.log(modalRef.current) this is what shows up in the console aka my entire JSX
I'm also using styled-components, so I only want to target the top div which I called Background but shows sc-bdnylx iEsAwc so I have no idea how to target it since it doesn't have any ids or classNames
I tried to add this console.log(modalRef.current.children[0]) but when I implemented it into my function, it didn't work properly. This console.log does only show the divs below my Background div, but I haven't found anything about targeting just the Background only
You don't actually need to use refs here. Just add onClick={e => e.stopPropagation()} to one of the divs inside Background, like on ModalWrapper. It'll stop the click from passing through.
How come the following React Button Emitter is not working? It should display the word Apple, with button click.
function App() {
return (
<div>
<button onClick={handleClick('apple')}>
Test Button
</button>
</div>
)
}
function handleClick(props) {
console.log(props)
}
In order for it to get called on click you need to pass a function. Right now your code is invoking the function:
function App() {
return (
<div>
{/* Creates an anonymous function that calls `handleClick` */}
<button onClick={() => { handleClick('apple'); }}>
Test Button
</button>
</div>
)
}
By doing onClick={handleClick('apple')} what you are doint is to put the result of handleClick('apple') at rendering time, not onClick time.
onClick={() => handleClick('apple')} will work because you are creating a function and assign it to onClick, without executing it yet.
This is how React works, because what you are writing is actually just javascript (not html, even if it looks like so).
Your way would instead be perfectly ok if you were using Vue, for example, because in that case you are working in an html template (unless you don't want to use jsx..)
Why does onClick not work directly on my custom element as shown here? The function chosenResource does not get invoked.
return (
<div>
{
resources.map(resource => {
return (
<SelectListItem key={resource.id} onClick={this.chosenResource.bind(this)} resource={resource} />
)
})
}
</div>
)
However, if I encapsulate my custom element in a div element and have the onClick on the div element then it works.
return (
<div>
{
resources.map(resource => {
return (
<div key={resource.id} onClick={this.chosenResource.bind(this)}>
<SelectListItem resource={resource} />
</div>
)
})
}
</div>
)
What is wrong with the first approach?
#nrgwsth is correct, if you still want to stick with your first approach, you may use:
return (
<div>
{
resources.map(resource => {
return (
<SelectListItem key={resource.id} customClickEvent={this.chosenResource.bind(this)} resource={resource} />
)
})
}
</div>
)
Then, in your SelectListItem's render() function, use like this:
return (
<div onClick={this.props.customClickEvent}>
...
</div>
)
You can provide onClick and other events only on DOM elements.
In react, we have components(ex. SelectListItem) and elements(ex.div). Elements are the basic building blocks for the component.
Elements are transpiled into plain javascript objects which represent DOM elements where we can bind the dom events like onCLick, onHover etc.
However Component returns the instance that contains a bunch of elements but does not correspond to the DOM element.
SO if you want to bind DOM event we should do it on the react elements, not in components.
In the above code, onClick event is passed down as props to the component which can be seen by logging the props of the compoenet.
I have an issue in my React.js app with the target id not being passed if a onClick event is attached on a div element.
This is how I add the component:
<MenuOption title="Users" onOptionClick={this.onOptionClick}/>
This is the jsx-part of my MenuOption component:
<div id={title} className="row menu-option" onClick={onOptionClick}>
<p>{title}</p>
</div>
As you can see I'm simply assigning the prop title as the id and the onClick event.
Back in the parent component, implementation of the onClick method:
onSidebarOptionClick(e) {
console.log(e.target.id);
}
This does not seem to work since it always logs undefined.
However, if I add the id and the onClick event to my p element instead...
<div className="row menu-option">
<p id={title} onClick={onOptionClick}>{title}</p>
</div>
...it works just as expected, the correct id logs at every click.
So why is not the id passed if the click event is attached to a div?
I`m using ES6 and babel.
I should clarify that I'm using "dumb" components, declaring them like this:
const MenuOption = ({title, onOptionClick})
...which is why don't need to use {this.props.title} when using it.
Not sure as your Question missing constructor but try one of the following--
Method 1 (JSX):
<MenuOption title="Users" onOptionClick={this.onOptionClick.bind(this)}/>
Method 2 (es6):
constructor(props) {
super(props);
this.onOptionClick = this.onOptionClick.bind(this);
}
Method 3(es-next):
onSidebarOptionClick = (e) => {
console.log(e.target.id);
}
As you're passing onOptionClick as a prop to <MenuOption/>, it should be declared as this.porops.onOptionClick.
<MenuOption/> should look like this
<div id={title} className="row menu-option" onClick={thi.props.onOptionClick}>
<p>{title}</p>
</div>
Hope this helps!