import React, { PropTypes } from 'react';
import Dialog from 'material-ui/Dialog';
export default class simpleModal extends React.Component {
constructor(props){
super(props)
}
handlePrimaryButton = () => {
this.props.router.push('/some/path');
}
render(){
return(
<Dialog
actions={<RaisedButton
label="OK"
primary={true}
onTouchTap={this.handlePrimaryButton}
/>}
modal={false}
open={this.props.open}
>
{this.props.msg}
</Dialog>
)
}
}
I created a wrapper using material-ui Dialog component but I can't open it. In another component I have this in my render method:
<simpleModal open={this.state.openSimpleModal} />
I then change the state of openSimpleModal using this.setState({openSimpleModal: true})
I don't see the modal being open. Is there anything missing in my above code? I manage to use Dialog component of material-ui directly but not with a wrapper.
Note: No error in chrome console at all.
Old thread but I had the same issue while using a wrapper. Had to use a callback to the parent, not pretty.
The Dialog component in material-ui-next doesn't have this issue any more.
Related
I'm working on a website about donation using Gatsby v2 (Reactjs) and I need an example like open modal window on button donation click using Gatsby or ReactJS. I search on internet and I got nothing.
Thanks in advance.
Here's a simple (Gatsby) page that makes use of react-modal as an example. In this example I've replaced the default IndexPage in the Gatsby v2's new starter site that you can generate via the CLI.
import React, { Component } from 'react'
import ReactModal from 'react-modal'
import { Link } from 'gatsby'
import Layout from '../components/layout'
ReactModal.setAppElement('#main')
class IndexPage extends Component {
constructor(props) {
super(props)
this.state = {
isModalOpen: false,
}
}
handleModalOpen = event => {
// console.log('handleModalOpen: ', event);
this.setState({ isModalOpen: true })
}
handleModalClose = event => {
// console.log('handleModalOpen: ', event);
this.setState({ isModalOpen: false })
}
render() {
return (
<Layout>
<div id="main">
<h1>Hi people</h1>
<p>Welcome to your new Gatsby site.</p>
<p>Now go build something great.</p>
<Link to="#" onClick={this.handleModalOpen}>
Donate Now
</Link>
</div>
<ReactModal
isOpen={this.state.isModalOpen}
onRequestClose={this.handleModalClose}
contentLabel="Example Modal In Gatsby"
>
<h2>Donate</h2>
<button onClick={this.handleModalClose}>Close Modal</button>
</ReactModal>
</Layout>
)
}
}
export default IndexPage
That should get you going. Best to read up on how to expand on this example using react-modal here (or use an alternative).
First of all the above example will not work because #main doesn't exist, right now the id for Gatsby app is ___gatsby, so it shoul look like this
ReactModal.setAppElement('#___gatsby')
But it's not good to hope that this id is not going to change in the future. So it's better to implement your own React modal component, here is a good example https://www.digitalocean.com/community/tutorials/react-modal-component
I've created an application to React, and when it starts, the App component is rendered. I would like that when the user clicks on a button or link, the button or link has to be in the App component when clicking on that link, another component will be rendered but not inside the App component but only the new component will be rendered in the same URL. As for this new component, it has to have a similar button so that when the user clicks, only the App component is rendered and this component that the user has clicked on is not rendered, only the App component.
I do not know if I explained myself correctly. Ask me any question if you need some clarification.
My App component is the following:
import React, { Component } from 'react';
import Touch from './Touch';
import '../App.css';
class App extends Component{
render() {
return(
<div>
<div className="wrapper" >
<button >NewComponent</button><NewComponent />???
<h1>Google Cloud Speech with Socket.io</h1>
<p id="ResultText"><span className="greyText">No Speech to Text yet</span></p>
</div>
<div className="buttonWrapper" >
<button className="btn" id="startRecButton" type="button"> Start recording</button>
<button className="btn" id="stopRecButton" type="button"> Stop recording</button>
</div>
</div>
);
}
}
export default App
My index.js is the following:
import React from 'react';
import ReactDOM from 'react-dom';
import './App.css';
import App from './components/App.js';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
If you really don't want to use react-router you will need to store a value in the component's state and change the rendering method to reflect which button was pressed. If you want each of those component to include the button you need to switch, do the following :
class App extends Component {
constructor(props){
super(props);
this.state = {renderA: false,};
}
handleClick = (event) => {
this.setState((prevState) => ({renderA: !prevState.renderA}));
};
render = () => {
return(
<div>
{this.state.renderA ?
<ComponentA handleClick={this.handleCLick}/>:
<ComponentB handleClick={this.handleCLick}/>
}
</div>
);
};
} export default App;
// ComponentA
class ComponentA extends Component {
render = () => {
return(
<div>
// what you want inside your first page here
<button onClick={this.props.handleClick}
</div>
);
}
} export default ComponentA;
// ComponentB
class ComponentB extends Component {
render = () => {
return(
<div>
// what you want inside your second page here
<button onClick={this.props.handleClick}
</div>
);
}
} export default ComponentB;
But using react-router might also suits your case, and if you are going to write a large app, you should use it instead of rendering differents children components within the same one, based on users inputs.
If the URL stay the same, I don't think React-Router might help you.
If you want that App Component is not loaded, I think you should create two more Component, a Wrapper one, and the new component you want to display (from now on newComponent). What I suggest is:
Creating a property isButtonClicked inside the state of the Wrapper Component;
Creating a function handleButtonClick() inside the Wrapper Component:
handleButtonClick() => {
let isButtonClicked = !this.state.isButtonClicked;
this.setState({ isButtonClicked });
}
In the render() method of the Wrapper component, you write something like this:
render() {
if (this.state.isButtonClicked)
return <App />
else
return <NewComponent />
}
Then, in both App and NewComponent, if you click on the button, you call the this.props.handleButtonClick(), which will lead to a change of the state of Wrapper Component, therefore to a change of what is shown on the screen.
I cannot believe that I cannot update state by setState.
I want to update cardModalOpen state to close the Modal.
I add bind(this) but it still does not work.
(Modal is opened by click Card Component)
However, I did setState({cardModalOpen: false}) by closeModal() function but it is still true even after render method was called.
Can someone please explain what I am doing wrong.
This is my code.
index.js
import React, { Component }from 'react';
import { Button, Card, Image, Header, Modal, Form, Input } from 'semantic-ui-react'
class App extends React.Component {
state = { cardModalOpen:false }
showCardModal() {
this.setState({cardModalOpen:true})
}
closeModal(){
this.setState({cardModalOpen:false})
}
render() {
const messagesDataNew = [];
for (var i = 0; i < 3; i++) {
messagesDataNew.push(
<Card
onClick={() => {
this.showCardModal();
}}
>
<DetailModal
cardModalOpen={this.state.cardModalOpen}
closeModal={this.closeModal}
/>
</Card>
);
}
return <div>{messagesDataNew}</div>;
}
}
DetailModal.js
import React, { Component }from 'react';
import { Button, Card, Image, Header, Modal, Form, Input } from 'semantic-ui-react'
class DetailModal extends Component{
render(){
return(
<Modal open={this.props.cardModalOpen} onClose={()=>{this.props.closeModal()}} >
<Modal.Header>Select a Photo</Modal.Header>
<Modal.Content image>
<Image wrapped size='medium' src='https://react.semantic-ui.com/images/avatar/large/rachel.png' />
<Modal.Description>
<Header>Default Profile Image</Header>
<p>We've found the following gravatar image associated with your e-mail address.</p>
<p>Is it okay to use this photo?</p>
</Modal.Description>
</Modal.Content>
<Button onClick={()=>{this.props.closeModal()}}>Close</Button>
</Modal>
)
}
}
export default DetailModal;
Here is a codesandbox with issue reproduced https://codesandbox.io/s/jjk7nw647y
In codesandbox you shared there is no clickable trigger-element for any of the modals. That's because of you are rendering an empty content of Card.
Here is my changes to your example https://codesandbox.io/s/l97n95n2om
The only difference is line #20 - I added a text Some text so your Card component has valid visible (and clickable) DOM element.
Do not forget bind your state handler functions:
constructor(props){
super(props)
this.showCardModal=this.showCardModal.bind(this)
this.closeModal =this.closeModal.bind(this)
}
I'm trying to add a Loader as Higher-Order-Component on button click in react/redux application.
Already have working Loader component and styling, just need to set logic when button is clicked show loader and hide existing button.
Button component:
import React from 'react'
import '../../../styles/components/_statement-print.scss';
import Loader from './Loader';
const StatementPrint = (props) => {
return (
<div>
<button
className="print-statement-button"
onClick={props.handleStatementPrint}>PRINT
</button>
</div>
);
};
export default Loader(StatementPrint);
Loader:
import React, { Component} from 'react';
import '../../../styles/components/_loader.scss';
const Loader = (WrappedComponent) => {
return class Loader extends Component {
render() {
return this.props.handleStatementPrint // Where must be logic when to show loader or existing button component
? <button className="loader-button">
<div className="loader">
<span className="loader-text">LOADING...</span>
</div>
</button>
: <WrappedComponent {...this.props} />
}
}
}
export default Loader;
In Loader component i added comment where need to write logic when to set loader or button.
I followed this example: ReactCasts - Higher Order Components
I searched a lot of examples but most of them shows how to set loader then is data is fetching, but in my case i just need to show then onClick method is triggered.
So how to set logic when onClick method is fired? Is this is a good aproach? Also it will be better to try acomplish this doing with redux state, but don't know how to do this.
Any help will be appreciated.
You will have to make small modifications to achieve what you want.
The wrapper component Loader can have a isLoading state, on the basis of which you can decide whether to show the loader span or the wrapped component.
This state isLoading can be updated by the wrapped component by passing showLoader function as a prop.
Button component
import React from 'react'
import '../../../styles/components/_statement-print.scss';
import Loader from './Loader';
const StatementPrint = ({handleStatementPrint, showLoader}) => {
return (
<div>
<button
className="print-statement-button"
onClick={() => {
showLoader();
handleStatementPrint();
}}>
PRINT
</button>
</div>
);
};
export default Loader(StatementPrint);
Loader
import React, { Component} from 'react';
import '../../../styles/components/_loader.scss';
const Loader = (WrappedComponent) => {
return class Loader extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: false
}
this.showLoader = this.showLoader.bind(this);
}
showLoader() {
this.setState({isLoading: true});
}
render() {
return this.state.isLoading
? <button className="loader-button">
<div className="loader">
<span className="loader-text">LOADING...</span>
</div>
</button>
: <WrappedComponent
{...this.props}
showLoader={this.showLoader}
/>
}
}
}
export default Loader;
EDIT
Since handleStatementPrint was required to be called, I have updated the click handler to include that function.
Also using de-structuring to avoid typing props repeatedly. See here for more info.
Just some external state is needed.
If you can't have external state (eg isLoading) than you could pass a function into a loader hoc which will derive isLoading from current props
Example: https://codesandbox.io/s/8n08qoo3j2
I desigining react native UI using Native base
library(http://docs.nativebase.io/Components.html#anatomy-headref). I am following their most basic example(the skeleton), but the Content Component is not showing up at all. Given that Most of the subcomponentes are depended on this, I am stuck on this library. I could render Grid which make sthis problem more weird for me. I am using there baseline example give in their documentation
http://docs.nativebase.io/Components.html#anatomy-headref ,only header is rendering.
import {Container,Header, Title, Button, Icon,Text} from 'native-base';
//Include Nativebase required components
import React from 'react';
import { StatusBar, StyleSheet ,View} from 'react-native'; //Most of the
react native components can be found in NativeBase
import { Font } from 'expo'; //to include font from expo.
// load up the child components
import BodyComponent from './body_container';
export default class ContainerApp extends React.Component {
//checking state for if font is loaded or not.
state = {
fontLoaded: false,
};
async componentDidMount() {
await Font.loadAsync({
'Roboto_medium': require('native-base/Fonts/Roboto_medium.ttf'),
});
//Setting the state to true when font is loaded.
this.setState({ fontLoaded: true });
}
render() {
return (
this.state.fontLoaded && (
<BodyComponent />
)
);
}
}
body component
export default class BodyComponent extends React.Component {
constructor(props){
super(props);
}
render(){
return(
<Container>
<Header>
<Left>
<Button transparent>
<Icon name='menu' />
</Button>
</Left>
<Body>
<Title>Header</Title>
</Body>
<Right />
</Header>
<Content>
<Text>
This is Content Section
</Text>
</Content>
</Container>
)
}
}
the ui showing up like (Pixel XL android)
The UI
I created repo https://github.com/abdullah2891/react_native_practice
In my case, the version of native base is changed. So I revert it and convert native-base: ^2.15.2