I have a few different const functions I would like to return and render. I have it set to always render out the Main menu unless a button is pressed, which updates my state to the name of the button. Each button name has another set of buttons that it should render out (exactly like main menu), but I can't get them to render out.
My current code renders the main menu and when a button is selected instead of rendering out a new line of buttons, it renders out just the name of the button selected. I would like my conditional to render out the state name component if possible.
this.state.selected is only rendering out a String. I would like to incase it in maybe...
<this.state.selected />
However, this doesn't work.
return (
<div>
{this.state.selected === '' ? <MainMenu /> : this.state.selected }
</div>
)
EDIT - Adding all of the code for more information
import React, { Component } from 'react'
import SearchBar from 'material-ui-search-bar'
import sass from '../scss/application.scss'
import PropTypes from 'prop-types'
import RaisedButton from 'material-ui/RaisedButton'
class OverviewRender extends Component {
constructor(props) {
super(props);
this.state = {
selected: ''
}
}
handleClick(name) {
this.setState({
selected: name
});
console.log("testing" + this.state.selected);
}
render() {
const MainMenu = () => (
<div>
<RaisedButton
label="File Options"
onClick={this.handleClick.bind(this, 'FileOptions')}
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
<RaisedButton
label="Setup Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
<RaisedButton
label="More Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
<RaisedButton
label="Shift Setup"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/> <br />
<RaisedButton
label="View/Report"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
<RaisedButton
label="Troubleshooting"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
</div>
);
const FileOptions = () => (
<div>
<RaisedButton
label="Load Values"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
<RaisedButton
label="Open Values From Disk"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
</div>
);
const { Selected } = this.state;
return (
<div>
{Selected === '' ? <MainMenu /> : <Selected />}
</div>
)
}
}
class Overview extends Component {
constructor(props){
super(props)
this.state = {
open: false
}
}
render() {
return (
<div className="menuButtons">
<br />
<OverviewRender />
</div>
)
}
}
export default Overview;
the best way if you could do this in your code
class Container extends React.Component {
constructor () {
super();
this.state = { Selected: null }
}
render () {
const { Selected } = this.state
return (
<div>
{Selected === '' ? <MainMenu /> : <Selected /> }
</div>
)
}
}
you must know that React will only render if follow its convention name. See again above
edit to reflect updated question above
import React, { Component } from 'react'
import SearchBar from 'material-ui-search-bar'
import sass from '../scss/application.scss'
import PropTypes from 'prop-types'
import RaisedButton from 'material-ui/RaisedButton'
const FileOptions = () => (
<div>
<RaisedButton label="Load Values" style={{ height: '80px', width: '180px', fontSize: '44px', padding: '1px'}} />
<RaisedButton label="Open Values From Disk" style={{ height: '80px', width: '180px', fontSize: '44px', padding: '1px'}} />
</div>
);
class OverviewRender extends Component {
constructor(props) {
super(props);
this.state = {
Selected: null
}
}
handleClick(name) {
this.setState({
Selected: name
});
console.log("testing" + this.state.Selected);
}
MainMenu = () => (
<div>
<RaisedButton label="File Options" onClick={() => this.setState({ Selected: FileOptions })} style={{ height: '80px', width: '180px', fontSize: '44px', padding: '1px' }} />
<RaisedButton label="Setup Options" style={{ height: '80px', width: '180px', fontSize: '44px', padding: '1px'}} />
<RaisedButton label="More Options" style={{height: '80px',width: '180px',fontSize: '44px',padding: '1px'}} />
<RaisedButton label="Shift Setup" style={{height: '80px',width: '180px',fontSize: '44px',padding: '1px'}} />
<br />
<RaisedButton label="View/Report" style={{ height: '80px', width: '180px', fontSize: '44px', padding: '1px' }} />
<RaisedButton label="Troubleshooting" style={{ height: '80px', width: '180px', fontSize: '44px', padding: '1px'}} />
</div>
)
render() {
const { Selected } = this.state;
return (
<div>
{this.MainMenu()}
{Selected === '' ? <MainMenu /> : <Selected />}
</div>
)
}
}
check again its initial state.
If this.state.selected is a string containing the component name, then I think this should work:
let SelectedComponent = this.state.selected;
return <div>{SelectedComponent ? <SelectedComponent /> : <MainMenu />}</div>;
The name of the variable containing the component must be capitalized. For more info see https://facebook.github.io/react/docs/jsx-in-depth.html#html-tags-vs.-react-components
Related
I'm new to react , and created a react modal component to show an image with its close button.
const BoxModal = ({children, modalIsOpen, setModalIsOpen}) => {
return (
<>
<Modal
isOpen={modalIsOpen}
onRequestClose={() => setModalIsOpen(false)}
style={{
overlay: {
backgroundColor: 'rgba(0, 0, 0, 0.3)',
zIndex: 2000,
},
content: {
top: '50%',
left: '50%',
right: 'auto',
bottom: 'auto',
border: 'none',
background: 'none',
transform: 'translate(-50%, -50%)',
padding: 0,
},
}}
>
{children}
<ButtonModal onClick={() => setModalIsOpen(false)}>
<img width={30} height={30} src={close_btn} alt="close" />
</ButtonModal>
</Modal>
</>
);
};
BoxModal.propTypes = {
children: PropTypes.element.isRequired,
modalIsOpen: PropTypes.bool,
setModalIsOpen: PropTypes.bool,
};
export default BoxModal;
Then, in another page I import I call it and import it like this:
<BoxModal>
<img
src={MapaRutas}
style={{
position: 'relative',
width: '100%',
}}
/>
</BoxModal>
<Button
width="260px"
height="60px"
color={'black'}
onClick={() => setModalIsOpen(true)}
>
<img width={13} height={13} src={map} alt="map" />
Ver cobertura de YoCargo
</Button>
I use react state to pass the onclick function in the button
const [modalIsOpen, setModalIsOpen] = useState(false);
But it's not working, nothing happens.Can someone tell me how to fix it ?
What i suggest is to set function to close your modal as prop in your BoxModal component, i call it 'handleClose', also you forget to pass 'modalIsOpen' to it.
import React, { useState } from 'react';
const Sample = () => {
const [modalIsOpen, setModalIsOpen] = useState(false);
return (
<>
<BoxModal modalIsOpen={modalIsOpen} handleClose={() => setModalIsOpen(false)}>
<img
src={MapaRutas}
style={{
position: 'relative',
width: '100%',
}}
/>
</BoxModal>
<Button
width="260px"
height="60px"
color={'black'}
onClick={() => setModalIsOpen(true)}
>
<img width={13} height={13} src={map} alt="map" />
Ver cobertura de YoCargo
</Button>
</>
);
}
In your BoxModel, you get the props like that
const BoxModal = ({children, modalIsOpen, handleClose }) => {
return (
<>
<Modal
isOpen={modalIsOpen}
onRequestClose={handleClose}
style={{
overlay: {
backgroundColor: 'rgba(0, 0, 0, 0.3)',
zIndex: 2000,
},
content: {
top: '50%',
left: '50%',
right: 'auto',
bottom: 'auto',
border: 'none',
background: 'none',
transform: 'translate(-50%, -50%)',
padding: 0,
},
}}
>
{children}
<ButtonModal onClick={handleClose}>
<img width={30} height={30} src={close_btn} alt="close" />
</ButtonModal>
</Modal>
</>
);
};
Suppose I have a component that takes in MeetingData as an object and populates a <p> element with specific items from that object:
import React from 'react';
export default function MeetingsCard({ meetingData }) {
return (
<div className="col-xl-1-12" style={{ margin: "10px", background: "#1A4565", border: "double" }}>
<div className="card" style={{ border: "none", width: "100%" }}>
<div className="card-body" style={{ width: "100%", background: "lightBlue" }}>
<h3 className="card-title" style={{ marginLeft: "10px" }}>Meetings</h3>
<p style={{ marginLeft: "50px" }}>Meeting location: {meetingData.meeting_location}, Meeting Date: {meetingData.meeting_date}</p>
<hr style={{ color: "grey" }} />
</div>
</div>
</div>
)
}
In this case, it expects there 2 be only a single item for meetingData.meeting_date and a single item for meetingData.meeting_location. But suppose the returned object has more than one and I need to populate multiple <p> elements? How would I do that if the meeting object/array looks like this:
meetingData = [
{
"date_time": "2021-07-07",
"meeting_location": "test-location1",
"name": "John Doe"
},
{
"date_time": "2021-07-08",
"meeting_location": "test-location2",
"name": "John Doe"
}
]
Just loop your data and add each entry as their own. Also good idea to create own component for the meeting entries so that it's easier to customize it if necessary.
MeetingEntry:
import React from 'react';
export default function MeetingEntry({ meetingData }) {
return (
<p style={{ marginLeft: "50px" }}>Meeting location: {meetingData.meeting_location}, Meeting Date: {meetingData.meeting_date}</p>
)
}
MeetingsCard:
import React from 'react';
import MeetingEntry from './MeetingEntry';
export default function MeetingsCard({ data }) {
return (
<div className="col-xl-1-12" style={{ margin: "10px", background: "#1A4565", border: "double" }}>
<div className="card" style={{ border: "none", width: "100%" }}>
<div className="card-body" style={{ width: "100%", background: "lightBlue" }}>
<h3 className="card-title" style={{ marginLeft: "10px" }}>Meetings</h3>
{data.map((el, idx) => (
<MeetingEntry notification={el} key={idx} />
))}
<hr style={{ color: "grey" }} />
</div>
</div>
</div>
)
}
You can just loop through the array and display data something like below
export default function MeetingsCard({ meetingData }) {
return (
<div className="col-xl-1-12" style={{ margin: "10px", background: "#1A4565", border: "double" }}>
<div className="card" style={{ border: "none", width: "100%" }}>
<div className="card-body" style={{ width: "100%", background: "lightBlue" }}>
<h3 className="card-title" style={{ marginLeft: "10px" }}>Meetings</h3>
{meetingData.map(meeting => (
<p style={{ marginLeft: "50px" }}>Meeting location: {meeting.meeting_location}, Meeting Date: {meeting.date_time}</p>))
<hr style={{ color: "grey" }} />
</div>
</div>
</div>
)
}
I have a react component that renders fine but as soon as i add images it renders far slower and causes a few hundred miliseconds delay on the component rendering. Does anyone know a way to speed this up or what I am doing wrong?
class SearchResults extends React.Component {
render() {
//Individual container styling
const divStyle = {
float: 'left',
width: '80px',
height: '80px',
border: '5px solid pink',
borderRadius: '3px',
margin: '2px',
cursor: 'pointer',
backgroundColor: 'white'
};
const styleImage = {
maxWidth: '70px',
maxHeight: '70px',
margin: 'auto',
display: 'flex'
}
//Individual record
const startItem = (this.props.itemsPerPage * this.props.page) - this.props.itemsPerPage;//First item on page
const endItem = startItem + this.props.itemsPerPage;
//Slice is from/to
const all = searchableDatabase.slice(startItem, endItem).map((value, index) => {
return (
<div style={divStyle} >
{value.edit_title_normal}
{/*<img style={styleImage} src={'YourMemories/' + currentCollection.id + '/' + value.sequentialNumber + '/' + value.sequentialNumber + ' Thumbnail.jpg'} />*/}
</div>
)
});
//Main container
return (
<div>
<div style={{ clear: 'both', paddingTop: '20px', paddingBottom: '20px', textAlign: 'center' }}>
<Pagination allLength={searchableDatabase.length} page={this.props.page} itemsPerPage={this.props.itemsPerPage} />
</div>
<div>
{all}
</div>
</div>
);
}
}
I'm trying to render out a few buttons, but for some reason nothing is happening. I'm not certain where my mistake is. I have an OverviewRender class which will eventually handle different sets of buttons to render and an Overview class which calls OverviewRender to render out the buttons.
It feels like should be working, but the buttons aren't rendering. If I move the buttons inside the Overview return function I see can see them.
import React, { Component } from 'react'
import SearchBar from 'material-ui-search-bar'
import sass from '../scss/application.scss'
import PropTypes from 'prop-types'
import RaisedButton from 'material-ui/RaisedButton'
class OverviewRender extends Component {
render() {
const mainMenu = () => {
return (
<div>
<RaisedButton label="File Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'}}
/>
<RaisedButton label="Setup Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'}}
/>
<RaisedButton label="More Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'}}
/>
</div>
)
}
return (
<div>
{mainMenu}
</div>
)
}
}
class Overview extends Component {
constructor(props){
super(props)
this.state = {
open: false
}
}
render() {
return (
<div className="menuButtons">
<OverviewRender />
</div>
)
}
}
export default Overview;
It's because you have created a function mainMenu that creates your buttons, but you never call it.
Two options:
1. Move the mainMenu return contents directly into the div:
class OverviewRender extends Component {
render() {
return (
<div>
<RaisedButton
label="File Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
<RaisedButton
label="Setup Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
<RaisedButton
label="More Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
</div>
)
}
}
2. Move mainMenu out of the component to make it a functional component, which looks like what you are trying to achieve. And then you have to use it like you would any other component: <MainMenu />:
class OverviewRender extends Component {
render() {
return <MainMenu />
}
}
const MainMenu = () => (
<div>
<RaisedButton
label="File Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
<RaisedButton
label="Setup Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
<RaisedButton
label="More Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'
}}
/>
</div>
);
User-Defined Components Must Be Capitalized
We recommend naming components with a capital letter. If you do have a component that starts with a lowercase letter, assign it to a capitalized variable before using it in JSX.
Just rename mainMenu to MainMenu an it should work.
See the docs: component must be capitalized
class OverviewRender extends React.Component {
render() {
const MainMenu = ({name}) => (
<div>
<button label="File Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'}}
/>
<button label="Setup Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'}}
/>
<button label="More Options"
style={{
height: '80px',
width: '180px',
fontSize: '44px',
padding: '1px'}}
/>
</div>
);
return (
<div>
<MainMenu/>
</div>
)
}
}
ReactDOM.render( < OverviewRender / > , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
I am completely new to React and I need to make an infinite scroll effect by including some divs from another component. I have found an infinite scroll library online and I am using it here in the index.js file. I have created my divs in Home.js but I am getting some errors like:-
Error: Mandatory prop "refreshFunction" missing. and TypeError: this.props.next is not a function. Can someone help me out please. I think even though I am exporting Home.js and then importing it in index.js but it is still not able to invoke the methods. Can someone please let me know what I am doing wrong and how to correct it? I have added the code below.
index.js
import React from 'react';
import { render } from "react-dom";
import InfiniteScroll from 'react-infinite-scroll-component';
import { Home } from "./components/Home";
class App extends React.Component{
render() {
return (
<InfiniteScroll
pullDownToRefresh
pullDownToRefreshContent={
<h3 style={{ textAlign: 'center' }}>↓ Pull down to refresh</h3>
}
releaseToRefreshContent={
<h3 style={{ textAlign: 'center' }}>↑ Release to refresh</h3>
}
refreshFunction={this.refresh}
next={this.generateDivs}
hasMore={true}
loader={<h4>Loading...</h4>}
endMessage={
<p style={{ textAlign: 'center' }}>
<b>Yay! You have seen it all</b>
</p>
}>
<Home/>
</InfiniteScroll>
);
}
}
render(<App />, window.document.getElementById("app"));
Home.js
import React from "react";
const style = {
display: 'flex',
alignItems: 'center',
fontSize: 40,
border: '2px solid red',
margin: ' 0 auto 10px auto',
textAlign: 'center'
}
const divs = [
<div key={1} style={{ height: 200, ...style }}>Div no 1</div>,
<div key={2} style={{ height: 200, ...style }}>Div no 2</div>,
<div key={3} style={{ height: 200, ...style }}>Div no 3</div>,
<div key={4} style={{ height: 200, ...style }}>Div no 4</div>,
<div key={5} style={{ height: 200, ...style }}>Div no 5</div>,
<div key={6} style={{ height: 200, ...style }}>Div no 6</div>,
<div key={7} style={{ height: 200, ...style }}>Div no 7</div>,
<div key={8} style={{ height: 200, ...style }}>Div no 8</div>,
];
export class Home extends React.Component{
constructor() {
super();
this.state = {
divs: divs
};
this.generateDivs = this.generateDivs.bind(this);
this.refresh = this.refresh.bind(this);
}
generateDivs() {
let moreDivs = [];
let count = this.state.divs.length;
console.log(count);
for (let i = 0; i < 30; i++) {
moreDivs.push(
<div key={'div' + count++} style={{ height: 200, ...style }}>
Div no {count}
</div>
);
}
setTimeout(() => {
this.setState({ divs: this.state.divs.concat(moreDivs) });
}, 500);
}
refresh() {
this.setState({ divs: [] });
setTimeout(() => {
this.setState({ divs });
}, 3000);
}
render() {
return (
<div>
{this.state.divs}
</div>
);
}
}