Inherit onclick in React - reactjs

I have the following Button component and the main file.
I want to be able to set "onclick" on the main file while keeping the original onclick behavior.
So in the following example, by clicking the button for now it does console.log "animated." only, but the desired result is "animated." and "clicked". (or vice versa)
Is it possible? Thanks.
// Button.jsx
export default function Button(props) {
function animate(e) {
console.log("animated.");
//
}
return (
<button
{...props}
ref={button}
onClick={e => {
animate(e);
}}
>
{props.children}
</button>
);
}
// main.js
import Button from "./Button.jsx"
..
<Button onClick={(e) => console.log("clicked.")}>
Text
</Button>

You can simply call the onClick from the props so that both gets executed.
export default function Button(props) {
function animate(e) {
console.log("animated.");
//
}
return (
<button
{...props}
ref={button}
onClick={e => {
animate(e);
if(props.onClick) props.onClick(e);
}}
>
{props.children}
</button>
);
}
Edit: as suggested in comment, you can also use Optional chaining (?.) instead of if statement.

Related

How to fix this error in react `onClick` listener to be a function, instead got a value of `string` type

I have this codes in react:
const [categoryId, setCategoryId] = useState("");
{
catName.map((singleCategory, index) => {
const { catName, _id: categoryId } = singleCategory;
return (
<>
<div
className="category-single-div flex-3 center-flex-align-display"
key={index}
>
<p className="text-general-small2 category-custom-text">{catName}</p>
<div className="category-icons-div ">
<FaEdit
className="category-icon-edit"
onClick={() => {
setEditCategory(true);
setCategoryId(categoryId);
}}
/>
<AiFillDelete className="category-icon-edit category-icon-delete" />
</div>
</div>
</>
);
});
}
I used map to get an array of objects, and I needed their individual _id when a user clicks the edit button. I also want to call another function on the same edit button via onClick. It is working but displays an error.
Warning: Expected onClick listener to be a function, instead got a
value of string type.
I need that _id so as to pass it to a state and have access to it globally within the component at the top level.
Is this workable?
Your problem comes from the FaEdit component.
<FaEdit
id={categoryId}
className="category-icon-edit"
onClick={(editCategory, id) => { // you need to have onClick as a prop defined inside the FaEdit component
setEditCategory(editCategory);
setCategoryId(id);
}}
/>
Example...
export default function FaEdit({className, onClick, categoryId}){
const handleChange() => {
onClick(true, categoryId)
}
return(
<div className={className} onClick={() => handleChange()}>Click</div>
)
}

I want to have a dialog as a separate component in React-MUI

I'm using React and MUI (v5)
I want to show a dialog in my component but I want this dialog as a separate component, like:
function MyComponent() {
const [ openDialog, setOpenDialog ] = useState(false);
const handleOpenDialog = () => {
setOpenDialog(true);
};
return (
<React.Fragment>
<Button variant="contained" size="medium" onClick={handleOpenDialog}>
Open Dialog
</Button>
<CreateCategory openDialog={openDialog} />
<Box>
...
</Box>
</React.Fragment>
);
}
and the dialog would be like:
export default function CreateCategory(props) {
const [openDialog, setOpenDialog] = useState(props.openDialog);
const [newCategoryName, setNewCategoryName] = useState("");
const handleDialogClose = () => {
setOpenDialog(false);
};
const handleAddCategory = (categoryName) => {
...
};
const handleCategoryNameChange = (e) => {
setNewCategoryName(e.target.value);
};
return (
<React.Fragment>
<Dialog
fullWidth
maxWidth={"sm"}
open={openDialog}
onClose={handleDialogClose}
>
<DialogTitle>Create Video Category</DialogTitle>
<DialogContent>
<TextField
...
/>
</DialogContent>
<DialogActions>
<Button ...>
Add Category
</Button>
<Button variant="outlined" onClick={handleDialogClose}>
Close
</Button>
</DialogActions>
</Dialog>
</React.Fragment>
);
}
But it is not working, I want to reuse the dialog in another component
I have it in code sandbox https://codesandbox.io/s/quizzical-merkle-ivquu?file=/src/App.js
Rafael
Copying props into state for no reason is an anti-pattern, and it's causing your issue.
You have two states called openDialog (one in the parent and one in the child), and are expecting them to operate as if they're the same.
To correct this, use props.openDialog directly in your component, and pass down the setter function as a prop as well. Then remove the local state version since it won't be used anymore.
// Pass the setter as well
<CreateCategory openDialog={openDialog} setOpenDialog={setOpenDialog} />
const handleDialogClose = () => {
props.setOpenDialog(false); // Use the prop.
};
<Dialog
fullWidth
maxWidth={"sm"}
open={props.openDialog} // Use value directly here
onClose={handleDialogClose}
>
In case this is also a source of confusion in the following snippet (which you should remove anyway):
const [openDialog, setOpenDialog] = useState(props.openDialog);
props.openDialog is only used once on the first render to initialize the state. Anytime in the future that the prop changes, the state will not change to match it. It is an initial value.

How can i get multiple recoil atoms when using components multiple?

In some components i am using recoil atoms to manage my states. One example is my modal component. It look something like this:
export const modalState = atom({
key: "modalState",
default: false
})
export const useToggleModalState = () => {
const setModalState = useSetRecoilState(modalState)
return (state, callback) => {
setModalState(state)
if (callback) {
callback()
}
}
}
export const Modal = (props) => {
<Transition show={modalState}>
<Dialog>
<Dialog.Title>My Modal Headline</Dialog.title>
<Dialog.Description>My Modal Description</Dialog.Description>
</Dialog>
</Transition>
}
and i am using this modal like this:
const toggleModalState = useToggleModalState();
return (
<Modal />
<Button text="Close Modal" onClick={() => toggleModalState(false)} />
)
however, if I use the modal multiple times, the modal is automatically duplicated, but I still use only one state for all modals. Of course, I don't want that. If I use a component multiple times, I want the state to be created multiple times, so that I can change the state of each component individually.
I have read that there are also atomFamilys. Could I use these at this point? What should my code look like then? Can multiple atoms also be created automatically if I use a component multiple times?
Why do you want to use recoil for that? The state of the modal is tied to the modal itself, it doesn't need to access global state.
You can just use useState to determine if you want to show a modal within a component:
export const Modal = (props) => {
<Transition show={props.show}>
<Dialog>
<Dialog.Title>My Modal Headline</Dialog.title>
<Dialog.Description>My Modal Description</Dialog.Description>
</Dialog>
</Transition>
}
export const ComponentWithModal = () => {
const [showModal, setShowModal] = useState(false);
return (
<>
<Modal show={showModal}/>
<Button text="Open Modal" onClick={() => setShowModal(true)} />
<Button text="Close Modal" onClick={() => setShowModal(false)} />
</>
)
}

How to use single button for two purpose

I made a component for one Button with animation effect so that i can use it in my other components by simply importing it. I did a lot of code in Button component for animation so i don't want to use a lot of same code again and again in other components.
Is there any way I can use the Button for different events by just importing. For example; In one component I import the Button as submitting the user information and in other component i am import the Button for displaying user data.
Of course! This is the components idea. You mught want to receive a prop in your Button to handle whatever happens onClick.
I.E.
Parent Component
create the especific function to handle
function handleClick() { ... }
<YourCustomButton onClick={handleClick} />
In YourCustomButton just use this function on event
class YourCustomButton extends React......
<Button onClick={this.props.onClick}> ...
Create a props for button to provide an option like
Implement in other component:
<custombutton mode={"submitmode"} clickevent={handleBtnClick} />
<custombutton mode={"displaymode"} clickevent={handleBtnClick} />
handleBtnClick=() =>{
if(mode =="submitmode"){
//..do code for submit
}
else if(mode=="displaymode"){
//..do code for display
}
}
Actual button component:
class Button extends custombutton{
handleClick =() =>{
this.props.clickevent();
}
render(){
return(
{props.mode=="submitmode" &&
<button type="submit" onClick={handleClick} class="submitstyle" />
}
{props.mode=="displaymode" &&
<button class="displaystyle" onClick={handleClick} />
}
);
}
}
Of course there is, just give it different props:
Example on codesandbox:
https://codesandbox.io/s/admiring-wing-okiqw
The parent:
function App() {
return (
<div className="App">
<h1>Hi there</h1>
<h2>Click on first button to sum 1, click to second button to sum 2!</h2>
<Fbutton functionality="sumone" />
<Fbutton functionality="sumtwo" />
</div>
);
}
You are calling Fbutton two times, one with sumone another with sumtwo props.
The son:
function Fbutton(props) {
const [count, setCount] = useState(0);
const sumone = () => setCount(count + 1);
const sumtwo = () => setCount(count + 2);
return (
<div>
<button onClick={props.functionality === "sumone" ? sumone : sumtwo}>
Sum: {count}
</button>
</div>
);
}
suppose you have a button like <Button pageName="home" />
And in that component suppose ,
class Button extends Compoenent {
onClick =()=>{
if(this.props.pageName == "home"){
// do your home action
} else if(this.props.pageName == "tab"){
// do your tab action
}
}
render(){
return(
<Button onClick={() => this.onClick()} />
)
}
}
Hope thats clear, feel free for doubts

React - onClick event not working correctly

I'm attempting to pass an onClick function as a prop to a child component in React. However, nothing is being logged to the console when the button is clicked. For now I'm just trying to console log to make sure the event is actually firing.
Any Ideas?
class App extends React.Component {
togglePallets = (pallet) => {
console.log('test');
}
render() {
return (
<div className="mainWrapper">
<div className="mainContainer">
<div>
<img src="images/picture-of-me.jpg" alt="Me"></img>
</div>
</div>
<SideBar toggle={this.togglePallets} showPallets={[this.state.showAboutPallet, this.state.showLanguagesPallet,
this.state.showProjectsPallet, this.state.showContactPallet]}/>
{this.state.showAboutPallet && <AboutPallet />}
{this.state.showAboutPallet && <LanguagesPallet />}
{this.state.showAboutPallet && <ProjectsPallet />}
{this.state.showAboutPallet && <ContactPallet />}
</div>
);
}
}
function SideBar(props) {
return (
<div className="sideBarContainer">
<Button icon={faUser} showAboutPallet={props.showPallets[0]} onClick={props.toggle}/>
</div>
);
}
What you have written is correct. But we can try it in another way using an arrow function.
onClick={(e) => props.toggle(e,data)}
And, make relevant changes in toggle function, so it may support multiple arguments.
Change your togglePallets to any of the below
togglePallets() {
console.log("test");
};
If you want to access event then
togglePallets(event) {
console.log("test");
};
Or
togglePallets=event =>{
console.log("teeventst");
};

Resources