I'm currently building a new React application, and am having a bit of trouble understanding the basics; I'm a complete beginner.
Bascially, what I need to do is have a button that, when clicked, opens up a container. Here is my thought process:
Create a main component, named "App". Within App, return a button.
The button, when clicked, should call another component that opens the container.
Some of what I have started on the code so far:
class handleClick extends React.Component{
constructor(props){
super(props);
this.state = {
isClicked: false
};
render(){
return(
);
}
}
}
function App(props){
//HAVE A COMPONENT TO TRIGGER THE CONTAINER
return(
<div>
<button>
Open photo entry dialog
</button>
</div>
);
I have no idea what to do. Any logic tips?
Thanks in advance!
To create model popup from parent to child component. Sample Demo App using react-bootstrap
npm install react-bootstrap bootstrap
Sample Code
App.js
import Model from "./Model";
class App extends React.Component {
state = { status: false };
handleClick = e => {
this.setState(prev => ({ status: !prev.status }));
};
render() {
const { status } = this.state;
return (
<>
<button onClick={this.handleClick}>Click to opent model</button>
{status && <Model status={status} handleClick={this.handleClick} />}
</>
);
}
}
Model.js
import "bootstrap/dist/css/bootstrap.min.css";
import { Button, Modal } from "react-bootstrap";
export default function Model({ handleClick, status }) {
return (
<>
<Modal show={status} onHide={handleClick}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClick}>
Close
</Button>
<Button variant="primary" onClick={handleClick}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
);
}
https://o1z0p.csb.app/
Related
I'm working on A React project with GraphQl back-end. I have a modal where a user can view more details about a subject. In that modal you can click delete which opens a new modal where you need to confirm if you wan't to delete. When yes is pressed it should be deleted and the modal should close. When no is pressed the modal should just close. The deleting of the subject works. If I press yes is deletes it but the modal doesn't close and when I press no the modal also doesn't close. Can anyone explain why and how I can fix this?
parent modal:
class CalenderModal extends React.Component {
constructor(props) {
super(props);
this.state = {
openDeleteAppointment: false,
};
this.openDeleteAppointment = this.openDeleteAppointment.bind(this);
}
handleRemove = () => {
this.props.onRemove();
}
openDeleteAppointment() {
this.setState({
openDeleteAppointment: true,
})
}
render() {
return (
<React.Fragment>
<div className="customModal">
<div className="modal-header">
<h5 className="customModal__text"> Appointment summary</h5>
<button className="btn modal__button__red" onClick={() => { this.openDeleteAppointment() }}>Delete</button>
{this.state.openDeleteAppointment &&
<DeleteAppointmentModal appointment={this.state.id} onHide={() => this.setState({ openDeleteClient: false, id: null })} show />}
</div>
<div className="modal-container">
<div className="summary">
<button className="btn modal__button__cancel" onClick={this.handleRemove}>Cancel</button>
</div>
</div>
}
</React.Fragment>
);
}
export default CalenderModal;
child modal:
class DeleteAppointmentModal extends React.Component {
constructor(props) {
super(props);
this.state = {
id: this.props.appointment,
};
}
render() {
const {id} = this.state
const DELETE_MUTATION = gql`
mutation DeleteMutation($id:ID! ) {
deleteAppointment(id:$id) {
id
}
}
`
console.log("delete id",this.state.id)
return (
<React.Fragment>
{
<Modal
{...this.props}
size="lg"
aria-labelledby="contained-modal-update-client"
centered
>
<Modal.Header closeButton >
<Modal.Title id="contained-modal-title-vcenter" className="tittle">Delete appointment </Modal.Title>
</Modal.Header>
<Modal.Body>
<div className="delete-content">
Are you sure you want to delete this appointment?
</div>
</Modal.Body>
<Modal.Footer>
<button onClick={() => this.props.onHide() } className="btn no">No</button>
<Mutation mutation={DELETE_MUTATION}
variables={{id}}>
{/* onCompleted={() => this.props.history.push('/')} */}
{deleteMutation =>
<button onClick={() => { deleteMutation(); this.props.onHide() }} className="btn yes">Yes</button>
}
</Mutation>
</Modal.Footer>
</Modal>
}
</React.Fragment>
);
}
}
export default DeleteAppointmentModal;
On "return" of parent component change the following row:
from:
<DeleteAppointmentModal appointment={this.state.id} onHide={() => this.setState({ openDeleteClient: false, id: null })} show />}
to:
<DeleteAppointmentModal appointment={this.state.id} onHide={() => { this.setState({ openDeleteAppointment: false, id: null }); handleRemove(); }} show />}
Hope it solved the problem.
From observation:
the show prop is always true. set show={this.state. openDeleteAppointment}
the onHide is not setting the right state. it should set openDeleteAppointment instead of openDeleteClient
I have create a very small app to demonstrate my query.
Below shown code has the functionality where the component is dynamically added to DOM using ReactDOM.render and this component carries a prop called title, but when I update the title of the parent component ( in state ) the DynamicComponent doesn't update.
import React from 'react';
import ReactDOM from 'react-dom';
const DynamicComponent = (props) => {
return (
<div style={{ 'border': '2px dotted green' }} >Dynamic Component : {props.title}</div>
)
}
class App extends React.Component {
state = {
title: 'Iam Title'
}
addBlock = () => {
return ReactDOM.render(<DynamicComponent title={this.state.title} />, document.getElementById('dynamiccomponents'))
}
render() {
return (
<div>
<div>Value in state: <b>{this.state.title}</b></div>
<p><b><DynamicComponent /></b> Added Initially</p>
<DynamicComponent title={this.state.title} />
<br />
<p><b><DynamicComponent /></b> Added By ReactDOM.render will be shown below: </p>
<div id="dynamiccomponents"></div>
<button onClick={this.addBlock} >Click to Dynamic Component</button>
<button onClick={() => this.setState({ title: `Update Title` })} >Update Title</button>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'));
The first button is used to added the DynamicComponent, works fine as expected.
The Second button is used to update the title in state, now the title got changed but still DynamicComponent doesn't update.
am I missing anything, how do I solve this issue, any help would be appreciated
Thanks
You could re-render the component after state change using a LifeCycle method componentDidUpdate()
import React from "react";
import ReactDOM from "react-dom";
const DynamicComponent = props => {
return (
<div style={{ border: "2px dotted green" }}>
Dynamic Component : {props.title}
</div>
);
};
class App extends React.Component {
state = {
title: "Iam Title"
};
addBlock = () => {
return ReactDOM.render(
<DynamicComponent title={this.state.title} />,
document.getElementById("dynamiccomponents")
);
};
componentDidUpdate() {
return ReactDOM.render(
<DynamicComponent title={this.state.title} />,
document.getElementById("dynamiccomponents")
);
}
render() {
return (
<div>
<div>
Value in state: <b>{this.state.title}</b>
</div>
<p>
<b><DynamicComponent /></b> Added Initially
</p>
<DynamicComponent title={this.state.title} />
<br />
<p>
<b><DynamicComponent /></b> Added By ReactDOM.render will be
shown below:{" "}
</p>
<div id='dynamiccomponents'></div>
<button onClick={this.addBlock}>Click to Dynamic Component</button>
<button onClick={() => this.setState({ title: `Update Title` })}>
Update Title
</button>
</div>
);
}
}
export default App;
This is because when you call addBlock, you are only rendering <DynamicComponent title={this.state.title} /> once to the <div id="dynamiccomopnents"></div>.
When you update the state of title by clicking the button, it re-runs your App's render function, but this.addBlock does not get run again in your render function and therefore your title does not get updated. You can verify this by clicking the button that calls this.addBlock again. It will render your component again, with the updated title.
I'd suggest you introduce some state to conditionally render your component instead of using ReactDOM.render. That way, your component gets re-rendered everytime your render method is run. Here's an example:
import React from 'react';
import ReactDOM from 'react-dom';
const DynamicComponent = (props) => {
return (
<div style={{ 'border': '2px dotted green' }} >Dynamic Component : {props.title}</div>
)
}
class App extends React.Component {
state = {
title: 'Iam Title',
showBlock: false,
}
addBlock = () => {
// this method now sets `this.state.showBlock` to true
this.setState({ showBlock: true });
}
renderBlock = () => {
// return any component you want here, you can introduce some conditional
// logic or even return nested elements, for example:
return (
<div>
<p>Dynamic Component!</p>
<DynamicComponent title={this.state.title} />
</div>
);
}
render() {
return (
<div>
<div>Value in state: <b>{this.state.title}</b></div>
<p><b><DynamicComponent /></b> Added Initially</p>
<DynamicComponent title={this.state.title} />
<br />
<p><b><DynamicComponent /></b> Added By ReactDOM.render will be shown below: </p>
{/* This will run `this.renderBlock` only if `this.state.showBlock` is true */}
{this.state.showBlock && this.renderBlock()}
<button onClick={this.addBlock} >Click to Dynamic Component</button>
<button onClick={() => this.setState({ title: `Update Title` })} >Update Title</button>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'));
ReactDOM.render renders element only once. It creates a different tree that is not connected to your first tree. That is, React doesn't keep track of all ReactDOM.renders you might have ever called and doesn't update them with data that was used to create them
If you need to render element somewhere in the DOM tree outside of your App component but you want it to be connected with your App component (so that it reacts to state changes), use ReactDOM.createPortal
I have a modal component called Modal.js and a main page component called Apps.js. What i want to achieve is, how can i load the modal box in modal.js as i navigate in to Apps.js. i.e I want to call Modal.js component first in my Apps.js component. The modal box should trigger and pop up once any user tries to load page Apps.js. How do i achieve that ?
PS: New to React
Modal.Js
function Transition(props) {
return <Slide direction="up" {...props} />;
}
export default class AlertDialogSlide extends React.Component {
state = {
open: false,
};
handleClose = () => {
this.setState({ open: false });
};
render() {
return (
<div>
<Dialog
open={this.state.open}
TransitionComponent={Transition}
keepMounted
onClose={this.handleClose}
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description"
>
<DialogTitle id="alert-dialog-slide-title">
</DialogTitle>
<DialogContent>
</DialogContent>
</Dialog>
</div>
);
}
}
Apps.JS
class Carts extends Component {
componentDidMount(){
}
}
Image
You can pass your open state via props.
You can do the following code into your modal file:
componentDidMount () {
this.setState({open: this.props.modalOpen})
}
Then into your App.js or another file, you just do:
<AlertDialogSlide modalOpen={true} />
In my parent class I have rendered a childclass compoment and passed another component to it as a prop and in the childclass component I want to load that component.
<EditRecordModal
show={this.state.showEditModal}
onHide={this.handleModalClose}
handleModalClose={this.handleModalClose}
dialogClassName="width-9x"
modalTitle="Edit data"
onUpdate={this.handleUpdate}
record={letter}
component={NewLetterEntryForm} >
</EditRecordModal>
export const EditRecordModal = (props) => {
return (
<Modal show={props.show} onHide={props.onHide} dialogClassName={props.dialogClassName}>
<Modal.Header closeButton>
<Modal.Title>{props.modalTitle}</Modal.Title>
</Modal.Header>
<Modal.Body>
// here I want to load that props.component like this
// <NewLetterEntryForm showPageHead={false} mode="edit" record={props.record} onUpdate={props.onUpdate} />
</Modal.Body>
<Modal.Footer>
<Button onClick={props.handleModalClose}>Close</Button>
</Modal.Footer>
</Modal>
)
}
I tried this but it won't work....still
export const EditRecordModal = (props) => {
const childComponent = props.component
return (
<Modal show={props.show} onHide={props.onHide} dialogClassName={props.dialogClassName}>
<Modal.Header closeButton>
<Modal.Title>{props.modalTitle}</Modal.Title>
</Modal.Header>
<Modal.Body>
{React.Children.map(childComponent, (child, i) => {
console.log(child)
return child
})}
</Modal.Body>
<Modal.Footer>
<Button onClick={props.handleModalClose}>Close</Button>
</Modal.Footer>
</Modal>
)
}
I am not sure why you need to pass child component as a props from the parent component. but if you want to use React.Children API, you should use like this:
<EditRecordModal
show={this.state.showEditModal}
onHide={this.handleModalClose}
handleModalClose={this.handleModalClose}
dialogClassName="width-9x"
modalTitle="Edit data"
onUpdate={this.handleUpdate}
record={letter}
>
<NewLetterEntryForm
//some your props
/>
</EditRecordModal >
and you also need to import your child component class before using it, add this line to the import area in your code: import NewLetterEntryForm from 'yourPathTo NewLetterEntryForm'
I'm following this PayPal tutorial about how to generate a PayPal button, but nothing works. The code it provides to make the button appear mysteriously worked only once for me, but after a refresh, it disappear and there's no Christ to make it appear again.
This is the code being executed inside of a React component
class Storefronts extends Component {
render() {
return (
<div className="layout-wrapper">
{this.props.location.pathname === '/shops' ? <Shops {...this.props}/> : <Basic {...this.props}/>}
<script>
window.paypalCheckoutReady = function() {
paypal.checkout.setup('MERCHANTID', {
environment: 'sandbox',
container: 'test1',
})
}
</script>
</div>
);
}
}
This is a Storefront component that holds a Shop, and inside this one has a Card component. Basically, it's a shop that shows its products, and each product (Card) needs to have a button:
class Card extends Editor {
render() {
const {list} = this.props;
let img = '/images/logo-v2-small.jpg';
return (
<Row>
{list.map(item =>{
return (
<Col xs={6} md={3}>
<Link to={{ pathname: '/shops/' + item.id }}>
<Thumbnail src={img} alt={item.name}>
<h3>{item.name}</h3>
<p>{this.parseHtmlToReact(item.description)}</p>
<p>{item.address}</p>
<p>
<Button bsStyle="primary">Book</Button>
<a id="test1" href="/checkout"/> // The button should appear here.
<p className="pull-right">
{item.rating}
</p>
</p>
</Thumbnail>
</Link>
</Col>
)
})}
</Row>
);
}
}
There's nothing saying about its usage with React and no recent module for it.
You could create your own PayPal Button component.
class PayPalButton extends React.Component {
constructor() {
super();
// you can take this value from a config.js module for example.
this.merchantId = '6XF3MPZBZV6HU';
}
componentDidMount() {
let container = this.props.id;
let merchantId = this.merchantId;
window.paypalCheckoutReady = function() {
paypal.checkout.setup(merchantId, {
locale: 'en_US',
environment: 'sandbox',
container: container,
});
}
}
render() {
return(
<a id={this.props.id} href="/checkout" />
);
}
}
ReactDOM.render(<PayPalButton id="button" />, document.getElementById('View'));
Working example on JSFiddle.