Hoc for popup does not work. Hock has a boolean state and two functions that change it. I pass them to the popup opening buttons and to the popup itself. The state changes through the console, but the popup itself does not open.
My HOC component
const Hoc = (Component) => {
const HandleChange = () => {
const [active, setActive] = useState(false);
function open() {
setActive(true)
}
function close() {
setActive(false)
}
useEffect(() => {
console.log(active)
}, [active])
return (
<Component activevvv={active} open={open} close={close} />
)
}
return HandleChange;
}
export default Hoc;
And my Button,the button works well, when you click on it, the state changes to true, I see this in the console log.
function ButtonsOur({ open }) {
return (
<div className="base__routes__button">
<Buttons className={"base__button__moreInf open-popup-exc"} Click={open} >Докладніше</Buttons>
<Buttons className={"base__button__moreInf open-popup-exc"} Click={open} >Забронювати</Buttons>
</div>
)
}
export default Hoc(ButtonsOur);
And my PopU. I pass the state of the current state to this component, and if the state is true, the popAp will be displayed. But nothing happens, although the state in the hockey changes.
function PopUpExc({activevvv, close}) {
return (
<div className={activevvv ? "popup__bg__exc active" : "popup__bg__exc"}>
<div className="popup__exc" onClick={e => e.stopPropagation()}>
<img onClick={close} src={Close} alt="close-popup" className="close-popup_exc" />
<div className="container">
<div className="row">
Related
This is the function where I am passing the onClick prop (setShowModal is setState() from the useState hook):
<MyFunctionalComponent
onClick={() => setShowModal(true)}
...other props here
/>
This is the functional component that receives the prop:
export const MyFunctionalComponent = ({ onClick }) => {
return (
<section>
...other code here
{onClick && (<Button>{ctaText}</Button>)}
</section>
);
};
But the Button component never appears, because the prop onClick is undefined. When I console.log the prop inside the functional component, it initially prints the function in the console, but then prints two more times as undefined. Could someone explain why that would be? I got it to work by spreading ...props instead. But the console.log remains the same? I don't understand why. This is my first question on Stack Overflow, so feel free to give me feedback on how to ask better questions :)
The reason why you are receiving an 'undefined' response is because as #Zrogua mentioned, onClick is an event listener function rather than a persistent value (like state you define).
import React from "react";
const YourButton = ({ onClick }) => {
console.log(onClick);
return <section>{onClick && <button>here</button>}</section>;
};
const ParentDiv = () => {
return (
<div>
<h1>Button Props</h1>
<h2>Start editing to see some magic happen!</h2>
<YourButton onClick={() => console.log("CLICK")} />
</div>
);
};
export default ParentDiv;
Result of console.log():
function onClick() // index.js:27:25
The reason why this is because props are read-only. From the React Docs:
Whether you declare a component as a function or a class, it must never modify its own props ... Such functions are called “pure” because they do not attempt to change their inputs, and always return the same result for the same inputs.
Therefore your button will only show if the onClick function is defined. For example, if you did not give onClick a function or value, the button will not appear:
import React, { useState } from "react";
const YourButton = ({ onClick }) => {
console.log(onClick);
return (
<section>
{onClick && <button>This button is shown if a button is defined.</button>}
</section>
);
};
const ParentDiv = () => {
return (
<div>
<h1>Button Props</h1>
<YourButton onClick={() => console.log("CLICK")} />
<YourButton /> {/* You won't see this button because the function is not defined. */}
</div>
);
};
export default ParentDiv;
The button appears because the prop has a value that is not undefined (your onClick function), and because it is read-only, you cannot access that function in your child component.
Instead, (1) define the modal state in the parent component and (2) pass the state through props to the button like so:
import React, { useState } from "react";
const YourButton = ({ onClick }) => {
console.log(onClick);
return (
<section>
{onClick && <button>This button is shown if a button is defined.</button>}
</section>
);
};
const AltButton = ({ modal }) => {
return (
<section>
{modal && (
<button>This button is shown the modal state is passed.</button>
)}
</section>
);
};
const ParentDiv = () => {
const [modal, setModal] = useState(false);
return (
<div>
<h1>Button Props</h1>
<YourButton onClick={() => console.log("CLICK")} />
<YourButton />{" "}
{/* You won't see this button because the function is not defined. */}
<section>
<button onClick={() => setModal(!modal)}>OPEN MODAL</button>
</section>
{modal && <p>this is dependent on state</p>}
<AltButton modal={modal} />
</div>
);
};
export default ParentDiv;
Working CodeSandbox: https://codesandbox.io/s/stack-66715327-passingfunctions-92pzr
Finally, if I am reading between the lines and understanding correctly that you are looking to hide a button when a modal is open, here is a little modal wrapper trick I use for buttons that open modals: https://codesandbox.io/s/stack-66715327-modalwrapper-wvl54
You can't pass onClick, onClick is just an event listener. You should pass the state
<MyFunctionalComponent onClick={() => setShowModal(!showModal)}
showModal={showModal}
...other props here />
/>
export const MyFunctionalComponent = ({ showModal }) => {
return (
<section>
...other code here
{showModal && (<Button>{ctaText}</Button>)}
</section>
);
};
I believe this should work. Let me know if this is what you were looking for.
I think that rather then passing callback you should pass variable which decide if component should show or not. Check this example.
export const MyFunctionalComponent = ({ isShow, onClick }) => {
return (
<section>
...other code here
{isShow && <div>something</div>}
</section>
);
};
export default function App() {
const [showModal, setShowModal] = useState(false);
return (
<MyFunctionalComponent
isShow={showModal}
onClick={() => setShowModal(true)}
/>
);
}
I also suppose that you can make mistake and have something other on mind .. like this:
<section>
...other code here
<button onClick={ onClick }>something</button>}
</section>
So basically I want when I press on the Button I want to Icon to disappear as well as Button. I have tried something but clearly, it is not working, so I would appreciate some help if possible
const Button = (props) => {
const[toggleIcon, setToggleIcon]=React.useState('true')
function Icon() {
toggleIcon(false)
}
return(
<div>
<button onClick={()=> setToggleIcon('false')}></button>
</div>
)
}
export default Button
const Icon = (props) => {
return(
<div>
<Icon>{props.Icon('false')}</Icon>
</div>
export default Icon
You can prevent a component from rendering by returning null. Use conditional rendering with the toggleIcon state as the condition. The onClick handler changes the state.
E.G.:
const Button = () => {
const [toggleIcon, setToggleIcon] = React.useState(true)
return toggleIcon ? (
<button onClick={() => setToggleIcon(false)}><Icon /></button>
) : null
}
export default Button
Take a look at the Conditional Rendering section of the React docs.
I am working on react project where i am trying to display toast using react-toastify , inside a div section when props ( isNotificationOpen ) is true. I tried an example something like bellow but i dont want the toast be triggered when button press occurs , i want the the tost to be triggered when isNotificationOpen props is set to true , how can i achieve this?
const notify = () => toast("Wow so easy !");
render() {
return (
<div className="d-flex" style={{ margin: "25px" }}>
<div className="mr-auto p-2">
{this.props.isNotificationOpen ? (
<div>
<div>
<button onClick={notify}>Notify !</button>
<ToastContainer />
</div>
//Show toast here...
</div>
) : (
<p />
)} ```
Use a component lifecycle function to respond to the isNotificationOpen prop changing to trigger a notfication.
Class-based component example
notify = () => toast('Wow so easy!');
componentDidMount() {
const { isNotificationOpen } = this.props;
isNotificationOpen && this.notify();
}
componentDidUpdate(prevProps) {
const { isNotificationOpen } = this.props;
if (prevProps.isNotificationOpen !== isNotificationOpen) {
isNotificationOpen && this.notify();
}
}
Functional component example
useEffect(() => {
props.isNotificationOpen && toast('Wow so easy!');
}, [props.isNotificationOpen]);
I'm trying to create a modal that asks users if they're an individual or organization, and then shows a sign up modal specific to that type of user. This is what I have so far:
parent:
this.state = {
showInd: false,
showOrg: false,
};
changeInd = () => {
this.setState({
showInd: !this.state.showInd
});
this.props.onClose(); //this closes the initial modal
}
//exact same syntax for changeOrg
render(){
return(
<div onClick={this.changeInd}>
<FontAwesomeIcon icon={faUser} className="fa-7x icon"/>
<span>individual</span>
</div>
<div onClick={this.changeOrg}>
<FontAwesomeIcon icon={faUsers} className="fa-7x icon"/>
<span>organization</span>
</div>
<SignUpInd show={this.state.showInd} />
<SignUpOrg show={this.state.showOrg} />
)}
and the child:
render(){
if (this.props.show){
return(
<various sign up html>
)}
}
The parent component is re-rendering when the state changes, but the child component is not, even though the props are changing. I've tried using componentDidUpdate, but that is also never triggered when the props change here.
What could I be doing wrong?
EDIT: So I've realized that if I comment out the line that closes the initial modal with a callback function, the signUpInd modal will render properly. Why can I not do both?
this works:
import React from "react";
import SignUpInd from "./SignUpInd";
import SignUpOrg from "./SignUpOrg";
import "./styles.css";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
showInd: false,
showOrg: false
};
}
showInd = () => {
this.setState((state) => ({ showInd: !state.showInd }));
};
showOrg = () => {
this.setState((state) => ({ showOrg: !state.showOrg }));
};
render() {
return (
<React.Fragment>
<div onClick={this.showInd}>
<FontAwesomeIcon icon={faUser} className="fa-7x icon"/>
<span>individual</span>
</div>
<div onClick={this.showOrg}>
<FontAwesomeIcon icon={faUsers} className="fa-7x icon"/>
<span>organization</span>
</div>
<SignUpInd show={this.state.showInd} />
<SignUpOrg show={this.state.showOrg} />
</React.Fragment>
);
}
}
1.At the parent component use a function that changes the state.
state = {
showInd: false,
showOrg: false,
};
stateChange = () =>{
this.setState({showInd:!this.state.showInd})
}
2.Use an onClick function on the div it will give opposite value of what it is right now and pass it as a props to the next component
<div onClick={this.stateChange}> //this onClick just flips showInd to the opposite of what it is currently - that's working properly
<span>individual</span>
</div>
<SignUpInd show={this.state.showInd} stateChange= {this.stateChange} />
3.At the other end just recieve the props and console log it
const {show,stateChange} = this.props
console.log(show);
I have a payment component and when I click a button, it should update the component state isOpen to true. This works fine in practice but when trying test it via enzyme, it wont update the prop.
The component looks like this:
class CashPayment extends Component {
state = {
isOpen: false
}
toggleModal = () => {
this.setState({ isOpen: true })
}
render() {
return (
<Mutation>
{() => (
<Fragment>
<Button
id="cash-payment-button"
onClick={this.toggleModal}
/>
<Modal
id="confirm-payment-modal"
isOpen={isOpen}
>
...
</Modal>
</Fragment>
)}
</Mutation>
)
}
}
So clicking #cash-payment-button should toggle the state isOpen which should open the modal.
In my test, I want to check the prop of my modal isOpen is set to true. But for some reason, the prop doesn't update in the test. However if I console log in my toggleIsOpen function, I can see the function gets called and the state updates.
My test is as so:
describe("Click Pay button", () => {
it("Should open confirm modal", () => {
Component = shallowWithIntl(
<CashPayment bookingData={bookingData} refetchBooking={refetchBooking} />
)
.dive()
.dive()
const button = Component.find("#cash-payment-button")
.props()
.onClick()
expect(Component.find("#confirm-payment-modal").prop("isOpen")).toEqual(true)
})
})
and the results are:
CashPayment › Click Pay button › Should open confirm modal
expect(received).toEqual(expected)
Expected value to equal:
true
Received:
false
Why does the modal component props not update?