first time exploring Gatsby and tried to install react-modal. Added modal component inside my ComponentOne and inside the modal is another component which is ComponentTwo where the close trigger resides. Already passed the onClick to ComponentTwo but still no luck. I think I miss something.
ComponentOne
import React, { Component } from "react"
import ComponentTwo from "./ComponentTwo"
import Modal from 'react-modal'
export default class ComponentOne extends Component {
constructor(props) {
super(props);
this.state = {
showModal: false
};
this.handleOpenModal = this.handleOpenModal.bind(this);
this.handleCloseModal = this.handleCloseModal.bind(this);
}
handleOpenModal() {
this.setState({ showModal: true });
}
handleCloseModal() {
this.setState({ showModal: false });
}
render() {
return (
<div className="container mx-auto h-50">
<Modal
isOpen={this.state.showModal}
ariaHideApp={false}
style={cotentStyle}
>
<ComponentTwo onClick={this.handleCloseModal} /> // this is component two
</Modal>
</div>
)
}
}
ComponentTwo
import React from 'react'
import { TiDelete } from 'react-icons/ti'
const NavContent = ({ data }, props) => (
<>
<div className="bg-black z-10 absolute inset-0">
<button onClick={props.onClick} className="text-white absolute top-0 right-0 my-4 mx-4">
<TiDelete size={'2em'} />
</button>
</div>
</>
)
export default function Nav(props) {
return (
<StaticQuery
query={worksQuery}
render={data => <NavContent data={data} {...props} />}
/>
)
}
Try with:
export default function Nav({onClick}) {
return (
<StaticQuery
onClick={onClick}
query={worksQuery}
render={data => <NavContent data={data} {...props} />}
/>
)
}
Related
import React, { Fragment, useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';
import { getPosts } from '../redux/actions/#posts';
import PostItem from '../components/posts/PostItem';
import CommentForm from '../components/posts/CommentForm';
import Comment from '../components/posts/Comment';
import '../styles/posts/postComponent.scss';
const Posts = ({
getPosts,
posts: { posts, isLoading },
isAuthenticated,
user
}) => {
useEffect(() => {
getPosts();
}, []);
const [show, toggleShow] = useState(false);
console.log(show);
const postsList = isLoading ? (
<div>posts are loading</div>
) : (
posts.map(post => {
return (
<div className='post'>
<PostItem
key={post._id}
auth={isAuthenticated}
user={user}
id={post._id}
title={post.title}
body={post.text}
author={post.name}
avatar={post.avatar}
date={post.date}
likes={post.likes}
comments={post.comments.map(comment => comment)}
toggleShow={toggleShow}
show={show}
/>
<CommentForm id={post._id} />
{post.comments.map(
comment =>
show && (
<Comment
key={comment._id}
comment={comment}
auth={isAuthenticated}
admin={user}
show={show}
/>
)
)}
</div>
);
})
);
return (
<Fragment>
<Link to='/add-post'>add Post</Link>
<div>{postsList}</div>
</Fragment>
);
};
Posts.propTypes = {
getPosts: PropTypes.func.isRequired,
posts: PropTypes.object.isRequired,
isAuthenticated: PropTypes.bool.isRequired
};
const mapStateToProps = state => {
// console.log(state.posts.posts.map(post => post.likes));
// console.log(state);
return {
posts: state.posts,
isAuthenticated: state.auth.isAuthenticated,
user: state.auth.user
};
};
export default connect(mapStateToProps, { getPosts })(Posts);
import React, { Fragment } from 'react';
import '../../styles/posts/postComponent.scss';
const Comment = ({
comment: { user, avatar, name, date, text },
admin,
auth
}) => {
return (
<Fragment>
<div className='c-container'>
<div className='c-img-text'>
<img className='c-img' height={'40px'} src={avatar} />
<div className='c-nt'>
<a href='#' className='c-n'>
{name}
</a>
<span className='c-t'> {text}</span>
<i className='c-d'>{date}</i>
</div>
{auth && admin
? admin._id === user && <div className='c-toggle'>...</div>
: ''}
</div>
</div>
</Fragment>
);
};
export default Comment;
I have a list of posts stored in redux, and mapped through it to create components. Now each component has a some body and comments.
I want to show the comments only after onClick event .
Below is the code I have come up with , and on Click it is toggling all the comments of all the Components.How can I toggle comments of an individual Component.
I am using react-admin framework and I am trying to put the <Edit> component inside <Drawer> component. I need this in order to be able to save changes done in my JsonInput.
This is my custom component:
import React, { Component, Fragment } from 'react';
import { fetchUtils, CardActions, EditButton, Button, List, Datagrid, Edit } from 'react-admin';
import Drawer from '#material-ui/core/Drawer';
import JsonInput from 'react-json-view';
import EditIcon from '#material-ui/icons/Edit';
import IconKeyboardArrowRight from '#material-ui/icons/KeyboardArrowRight';
import { SimpleForm } from 'ra-ui-materialui/lib/form';
const divStyle = {
width: '400px',
margin: '1em'
};
export default class JsonEditButton extends React.Component {
constructor(props, context) {
super(props, context);
this.state = { showPanel: false };
}
handleClick = () => {
this.setState({ showPanel: true });
};
handleCloseClick = () => {
this.setState({ showPanel: false });
};
onChange = (value) => {
const { updated_src, name, namespace, new_value, existing_value } = value;
//this.onChange(updated_src);
}
render() {
const { showPanel } = this.state;
return (
<div>
<Button label="Upravit JSON" onClick={this.handleClick}>
<EditIcon />
</Button>
<Fragment>
<Drawer
anchor="right"
open={showPanel}
onClose={this.handleCloseClick}
>
<div>
<Button label="Zavřít" onClick={this.handleCloseClick}>
<IconKeyboardArrowRight />
</Button>
</div>
<div style={divStyle}>
{props => (
<Edit {...props}>
<SimpleForm>
{this.props.record && <JsonInput src={this.props.record} name={null} displayDataTypes={false} displayObjectSize={false} onEdit={this.onChange} onAdd={this.onChange} onDelete={this.onChange} />}
</SimpleForm>
</Edit>
)}
</div>
</Drawer>
</Fragment>
</div>
);
}
};
However this doesnt return any HTML.
Any idea how to solve this?
Thank you in advance.
Maybe this may help
<div style={divStyle}>
<Edit {...this.props}>
<SimpleForm>
{this.props.record && <JsonInput src={this.props.record} name={null} displayDataTypes={false} displayObjectSize={false} onEdit={this.onChange} onAdd={this.onChange} onDelete={this.onChange} />}
</SimpleForm>
</Edit>
</div>
the previous code where {props => ()} is actually a function or you could try this
<div style={divStyle}>
{props => (
return(
<Edit {...props}>
<SimpleForm>
{this.props.record && <JsonInput src={this.props.record} name={null} displayDataTypes={false} displayObjectSize={false} onEdit={this.onChange} onAdd={this.onChange} onDelete={this.onChange} />}
</SimpleForm>
</Edit>)
)}
</div>
I have 2 components that I want to display based on the state.
basically when I click the button I want to toggle 2 components. I dont understand why when I click the button nothing changes.
import React, { Component } from 'react';
import { Route, Link, NavLink, Redirect } from 'react-router-dom'
class Header extends Component {
constructor(props) {
super(props);
this.state = {isToggleOn: false};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return(
<header>
{this.state.isToggleOn ? <MenuOpened /> : <MenuClosed />}
</header>
)
}
}
const MenuClosed = () => {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
)
}
const MenuOpened = () => {
return(
<ul>
<li><NavLink to="/page-1" exact>page1</NavLink></li>
<li><NavLink to="/page-2" exact>page2</NavLink></li>
</ul>
)
}
export default Header;
You gotta pass handleClick function and isToggleOn state as props to MenuClosed component.
{this.state.isToggleOn ? <MenuOpened /> : <MenuClosed handleClick={this.handleClick} isToggleOn={this.state.isToggleOn} />}
And then:
const MenuClosed = ({handleClick, isToggleOn}) => { return ( <button onClick={handleClick}> {isToggleOn ? 'ON' : 'OFF'} </button> ) }
I'm new for React and Material-UI too. I have this App.js file:
import React, {Component} from 'react';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import AppBar from 'material-ui/AppBar';
import IconButton from 'material-ui/IconButton';
import NavigationMenu from 'material-ui/svg-icons/navigation/menu';
import DrawerMenu from './DrawerMenu';
const AppBarIcon = () => (
<AppBar
title="Title"
iconElementLeft={<IconButton onClick={???}>
<NavigationMenu />
</IconButton>}
/>
);
class App extends Component {
render() {
return (
<div className="App">
<MuiThemeProvider>
<div>
<DrawerMenu />
<AppBarIcon />
</div>
</MuiThemeProvider>
</div>
);
}
}
export default App;
...and this is the DrawerMenu.js file:
import React from 'react';
import Drawer from 'material-ui/Drawer';
import MenuItem from 'material-ui/MenuItem';
export default class DrawerSimpleExample extends React.Component {
constructor(props) {
super(props);
this.state = {open: false};
}
handleToggle = () => this.setState({open: !this.state.open});
render() {
return (
<div>
<Drawer open={this.state.open}>
<MenuItem>Menu Item</MenuItem>
<MenuItem>Menu Item 2</MenuItem>
</Drawer>
</div>
);
}
}
Is there any way to set the IconButton's onClick value in App.js file to set the DrawerMenu's state open:true ? For example:
<IconButton onClick={ DrawerMenu.setState({open:true}) }>
...or something like this?
You can use props to achieve desired behavior.
Example
const AppBarIcon = (props) => (
<AppBar
title="Title"
iconElementLeft={<IconButton onClick={props.onIconClick}>
<NavigationMenu />
</IconButton>}
/>
);
class App extends Component {
constructor(props) {
super(props);
this.state = { isOpen: false };
}
onIconClick = () => {
this.setState((prevState) => ({ isOpen: !prevState.isOpen }));
}
render() {
return (
<div className="App">
<MuiThemeProvider>
<div>
<DrawerMenu isOpen={this.state.isOpen} />
<AppBarIcon onIconClick={this.onIconClick} />
</div>
</MuiThemeProvider>
</div>
);
}
}
export default class DrawerSimpleExample extends React.Component {
constructor(props) {
super(props);
this.state = {open: false};
}
handleToggle = () => this.setState({open: !this.state.open});
render() {
return (
<div>
<Drawer open={this.props.isOpen}>
<MenuItem>Menu Item</MenuItem>
<MenuItem>Menu Item 2</MenuItem>
</Drawer>
</div>
);
}
}
I have the following spinner
import React, { Component } from 'react'
import './Spinner.scss'
export default class Spinner extends Component {
constructor(props) {
super(props);
this.state = {showLoading: true};
}
render () {
return (
<div className="spinner">
<div className="double-bounce1"></div>
<div className="double-bounce2"></div>
</div>
)
}
}
and from other component I would like to show or hide this spinner here is the code of the component:
import React, { Component } from 'react'
import RTable from '../../../components/RTable/RTable'
import Spinner from '../../../components/Spinner/Spinner'
import CsvDownload from '../containers/CsvDownloadContainer'
export default class Table extends Component {
_renderBreadcrumb () {
const { breadcrumb, handleBreadcrumbClick } = this.props
return (
<ol className="breadcrumb">
{(breadcrumb || []).map(el => {
return (
<li key={el.datasetKey}>
<a onClick={() => { handleBreadcrumbClick(el.granularity, el.datasetKey, el.datasetKeyHuman) }}>
{el.datasetKeyHuman}
</a>
</li>
)
})}
</ol>
)
}
render () {
const { datasetRows, columns, metadata, showLoading } = this.props
return (
<div className="row">
<div className="col-sm-12">
{this._renderBreadcrumb()}
<RTable rows={datasetRows} columns={columns} metadata={metadata} />
{ this.props.showLoading ? <Spinner /> : null }
<CsvDownload />
</div>
</div>
)
}
}
as you can see I trying to show or hide the spinner using:
{ this.props.showLoading ? <Spinner /> : null }
but I'm always getting undefinde. Some help please.
You have to move this
constructor(props) {
super(props);
this.state = {showLoading: true};
}
to your <Table /> component, otherwise you access showLoading from <Table />'s props, but it is not passed from anywhere.
Then change also
{ this.props.showLoading ? <Spinner /> : null }
to
{ this.state.showLoading ? <Spinner /> : null }
To show / hide <Spinner /> just call this.setState({ showLoading: Boolean }) in your <Table /> component.