I have a list of results from my search output. Each result has an onclick function. I want to display each of the results that the user clicks, and for now I can add each result that the user clicks to an array using this function:
let selectedData = []
function addFunc(resultdata){
console.log(resultdata)
selectedData = [...selectedData, resultdata]
console.log(selectedData)
};
I'm new to React, but I know this isn't the right way and I might have to use states or react hooks. The problem is that because I am using Elasticsearch to output the results, my results are in a function, not the main class. Like this:
class Search extends Component {
render() {
return (
<div>
<ReactiveBase
app="datataglist"
credentials="mRgWyoKGQ:f47be2a6-65d0-43b6-8aba-95dbd49eb882"
url="https://scalr.api.appbase.io"
>
<DataSearch
componentId="search"
dataField={[
"maker_tag_name",
"maker_tag_name.autosuggest",
"maker_tag_name.keyword"
]}
fieldWeights={[6, 2, 6]}
fuzziness={1}
highlightField={["maker_tag_name"]}
placeholder="Search Tag Name"
style={{
marginBottom: 20
}}
title="Maker Tag Name"
/>
<Row gutter={16}>
<Col span={8}>
<MultiList
componentId="system"
dataField="system.keyword"
queryFormat="or"
size={100}
sortBy="asc"
style={{
marginBottom: 20
}}
title="System"
/>
</Col>
<Col span={8}>
<MultiList
componentId="grouping"
dataField="grouping.keyword"
size={100}
style={{
marginBottom: 20
}}
title="Grouping"
/>
</Col>
<Col span={8}>
<MultiList
componentId="unit"
dataField="units.keyword"
size={100}
style={{
marginBottom: 20
}}
title="Unit"
/>
</Col>
</Row>
<SelectedFilters />
<ReactiveList
componentId="results"
dataField="_score"
pagination={true}
react={{
and: ["system", "grouping", "unit", "search"]
}}
size={10}
noResults="No results were found..."
renderItem={RenderItem}
/>
</ReactiveBase>
<div>
</div>
</div>
);
}
}
function getNestedValue(obj, path) {
const keys = path.split(".");
const currentObject = obj;
const nestedValue = keys.reduce((value, key) => {
if (value) {
return value[key];
}
return "";
}, currentObject);
if (typeof nestedValue === "object") {
return JSON.stringify(nestedValue);
}
return nestedValue;
}
function RenderItem(res, triggerClickAnalytics) {
let { unit, title, system, score, proposed, id } = {
title: "maker_tag_name",
proposed: "proposed_standard_format",
unit: "units",
system: "system",
score: "_score",
id: "_id"
};
title = getNestedValue(res, title);
system = getNestedValue(res, system);
unit = getNestedValue(res, unit);
score = getNestedValue(res, score);
proposed = getNestedValue(res, proposed);
id = getNestedValue(res, id);
const resultdata = {id, title, system, unit, score, proposed}
return (
<Row
onClick={triggerClickAnalytics}
type="flex"
gutter={16}
key={res._id}
style={{ margin: "20px auto", borderBottom: "1px solid #ededed" }}
>
<Col style={{ width: "360px" }}>
<h3
style={{ fontWeight: "600" }}
dangerouslySetInnerHTML={{
__html: title || "Choose a valid Title Field"
}}
/>
</Col>
<div style={{ padding: "20px" }} />
<Col>
<p
style={{ fontSize: "1em", width: "300px" }}
dangerouslySetInnerHTML={{
__html: system || "Choose a valid Description Field"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col>
<p
style={{ fontSize: "1em" }}
dangerouslySetInnerHTML={{
__html: unit || "-"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col style={{ minWidth: "120px" }}>
<p
style={{ fontSize: "1em", width: "300px"}}
dangerouslySetInnerHTML={{
__html: proposed || "Choose a valid Description Field"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col>
<p
style={{ fontSize: "1em"}}
dangerouslySetInnerHTML={{
__html: Math.round(score) || "Choose a valid Description Field"
}}
/>
</Col>
<Col>
<Button
shape="circle"
icon={<CheckOutlined />}
style={{ marginRight: "5px" }}
onClick={()=> {addFunc(resultdata)}}
/>
</Col>
</Row>
);
}
Basically, my ReactiveList component is what shows the results. This calls the RenderItem function, which is what displays the data on the screen. In my function, I have a list called resultdata, which contains all the data I need when each result is clicked on. This works, but I need it to display on the screen.
I can't use state, because I have a function. And I can't use hooks because it isn't the main function. Am I doing something wrong? Is there any other alternative to this?
Even if you can't provide a complete answer, I would appreciate any tips on which direction I should look towards.
state is async so it wont update like this:
function addFunc(resultdata){
console.log(resultdata)
selectedData = [...selectedData, resultdata]
console.log(selectedData)
};
and you are using a class so you can't useHooks but setState takes a callback as second argument
function addFunc(resultdata){
console.log(resultdata)
this.setState({selectedData: [...selectedData, resultdata]}, () => console.log(selectedData))
};
so if you continue using a Class approach this will allow you to use setState and utilize the callback in it
there is a callback available too in hooks but it doesn't work quite the same
Place addFunc within the parent component and make your RenderItem function a React Functional component by exporting it. Then provide the addFunc as a function prop from parent component to RenderItem component. That way you can call the function within onClick event. Any of the parent states can be updated from the addFunc. You can supply necessary arguments to the function call as well.
Related
I am building a forum and I want to make it where: Once you click on the title, it displays a page (which I already created) that displays the post title and then the post body. I used MUI to build the page as well. However, the Axios call fails when I call the backend and appending the "this.state.props." to the end.
My "All Questions" page code in which the user which select which post to open:
export default class DisplayPosts extends Component {
constructor(props) {
super(props);
this.state = {
posts: [],
selectedPostId: null,
};
}
componentDidMount (){
axios.get('http://localhost:6006/api/v1/posts')
.then(res=> {
const posts = [];
for (let key in res.data.data) {
posts.push({...res.data.data[key], id: key});
}
this.setState({
posts: posts,
})
console.log('Pulling From:: ', res.data.data)
})
.catch(err => console.log('err:: ', err)
)
}
onPostClickHandler = (_id) => {
this.setState({
selectedPostId: _id,
})
console.log(_id)
}
render() {
const posts = this.state.posts.map((post) => {
return <Posts
key ={post._id}
post={post}
postclicked = {this.onPostClickHandler.bind(
this,
post._id,
)} />;
})
return (
<Box component="main"
sx={{ flexGrow: 1, p: 3, marginLeft: "300px",marginTop:"-40px" }}>
<Toolbar />
<Stack spacing={2}>
<Typography>
<h1> All Questions </h1>
</Typography>
<Button
sx={{}}
variant = 'outlined'
size = 'medium'
color = 'secondary'>
Ask New Question
</Button>
<Divider />
<div>
{posts}
</div>
</Stack>
{this.state.selectedPostId && (
<ViewPosts _id={this.state.selectedPostId} />
)}
</Box>
)
}
}
My "View Posts" page, the page where the user will see the information of the post they just clicked
export default class ViewPosts extends Component {
constructor(props){
super(props);
this.state = {
post: null,
}
}
componentDidMount (){
axios.get(`http://localhost:6006/api/v1/posts/${this.props._id}`)
.then(res=> {
this.setState({
posts: {...res.data.data, _id: this.props._id}
})
console.log('Pulling From:: ', res.data.data)
})
.catch(err => console.log('err:: ', err)
)
}
render() {
return (
<div>
<><Box component="main"
sx={{ flexGrow: 1, p: 3, marginLeft: "300px", marginTop: "-40px" }}>
<Toolbar />
<Typography>
<h1>{this.state.post.title} </h1>
<p>Added: Today ..........Viewed: -- times </p>
</Typography>
<Divider />
<Stack direction='row' spacing={3}>
<Stack
direction="column"
spacing={2}>
<IconButton>
<KeyboardDoubleArrowUpIcon color='primary' />
</IconButton>
<IconButton sx={{ marginTop: '2px' }}>
<KeyboardDoubleArrowDownIcon color='primary' />
</IconButton>
</Stack>
<Typography>
<h6> </h6>
</Typography>
<Typography>
<p>
{this.state.post.body}
</p>
</Typography>
</Stack>
<Divider />
<TextField
sx={{ marginTop: "20px", marginLeft: "0px", width: '950px' }}
id="filled-multiline-static"
label="Enter Answer Here..."
multiline
rows={8}
variant="filled" />
<Button
sx={{ marginTop: "15px" }}
variant='contained'
size='large'
color='primary'
>
Post Your Answer
</Button>
</Box>
</>
</div>
)
}
}
From my understanding, componentDidMount is called after the component is mounted.
And by that, I mean the axios call will happen immediately, while the DOM content will take more time to load.
So, chances are, what happens is that you're not going to see anything, even if the axios call is finished and the state of the ViewPost is no longer null.
What you may wanna do now is to create a logic that prevents the DOM of the post from being displayed until the state is populated.
Like, for example...
render() {
return this.state.post && (
<div>
<><Box component="main"
sx={{ flexGrow: 1, p: 3, marginLeft: "300px", marginTop: "-40px" }}>
<Toolbar />
<Typography>
<h1>{this.state.post.title} </h1>
<p>Added: Today ..........Viewed: -- times </p>
</Typography>
<Divider />
<Stack direction='row' spacing={3}>
<Stack
direction="column"
spacing={2}>
<IconButton>
<KeyboardDoubleArrowUpIcon color='primary' />
</IconButton>
<IconButton sx={{ marginTop: '2px' }}>
<KeyboardDoubleArrowDownIcon color='primary' />
</IconButton>
</Stack>
<Typography>
<h6> </h6>
</Typography>
<Typography>
<p>
{this.state.post.body}
</p>
</Typography>
</Stack>
<Divider />
<TextField
sx={{ marginTop: "20px", marginLeft: "0px", width: '950px' }}
id="filled-multiline-static"
label="Enter Answer Here..."
multiline
rows={8}
variant="filled" />
<Button
sx={{ marginTop: "15px" }}
variant='contained'
size='large'
color='primary'
>
Post Your Answer
</Button>
</Box>
</>
</div>
)
}
}
I am building a search filter of sorts using Elasticsearch and ReactiveSearch for UI.
Each result has an ID, title, etc that I can call to display it when a user searches. I need a button for each results, and when the user clicks it, it should 'add to cart' or something like that. I just need the clicked results to be shown in the next page.
The code below is my search field, and the results that are shown. I have an onclick function, but I don't know how to proceed after that. I think I need to use redux.
class Results extends Component {
render() {
return (
<ReactiveBase
app="datataglist"
credentials="mRgWyoKGQ:f47be2a6-65d0-43b6-8aba-95dbd49eb882"
url="https://scalr.api.appbase.io"
>
<DataSearch
componentId="search"
dataField={[
"maker_tag_name",
"maker_tag_name.autosuggest",
"maker_tag_name.keyword"
]}
fieldWeights={[6, 2, 6]}
fuzziness={1}
highlightField={["maker_tag_name"]}
placeholder="Search Tag Name"
style={{
marginBottom: 20
}}
title="Maker Tag Name"
/>
<SelectedFilters />
<ReactiveList
componentId="results"
dataField="_score"
pagination={true}
react={{
and: ["system", "grouping", "unit", "search"]
}}
size={10}
noResults="No results were found..."
renderItem={renderItem}
/>
</ReactiveBase>
);
}
}
function getNestedValue(obj, path) {
const keys = path.split(".");
const currentObject = obj;
const nestedValue = keys.reduce((value, key) => {
if (value) {
return value[key];
}
return "";
}, currentObject);
if (typeof nestedValue === "object") {
return JSON.stringify(nestedValue);
}
return nestedValue;
}
function renderItem(res, triggerClickAnalytics) {
let { url, unit, title, system, score, proposed, id } = {
title: "maker_tag_name",
proposed: "proposed_standard_format",
unit: "units",
system: "system",
score: "_score",
url: "",
id: "_id"
};
title = getNestedValue(res, title);
system = getNestedValue(res, system);
url = getNestedValue(res, url);
unit = getNestedValue(res, unit);
score = getNestedValue(res, score);
proposed = getNestedValue(res, proposed);
id = getNestedValue(res, id);
return (
<Row
onClick={triggerClickAnalytics}
type="flex"
gutter={16}
key={res._id}
style={{ margin: "20px auto", borderBottom: "1px solid #ededed" }}
>
<Col style={{ width: "360px" }}>
<h3
style={{ fontWeight: "600" }}
dangerouslySetInnerHTML={{
__html: title || "Choose a valid Title Field"
}}
/>
</Col>
<div style={{ padding: "20px" }} />
<Col>
<p
style={{ fontSize: "1em", width: "300px" }}
dangerouslySetInnerHTML={{
__html: system || "Choose a valid Description Field"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col>
<p
style={{ fontSize: "1em" }}
dangerouslySetInnerHTML={{
__html: unit || "-"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col style={{ minWidth: "120px" }}>
<p
style={{ fontSize: "1em", width: "300px"}}
dangerouslySetInnerHTML={{
__html: proposed || "Choose a valid Description Field"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col>
<p
style={{ fontSize: "1em"}}
dangerouslySetInnerHTML={{
__html: Math.round(score) || "Choose a valid Description Field"
}}
/>
</Col>
<Col>
<Button
shape="circle"
icon={<CheckOutlined />}
style={{ marginRight: "5px" }}
onClick={()=>{this.handleClick(id)}}
/>
</Col>
<Col style={{ minWidth: "120px" }}>
<p
style={{ fontSize: "1em", width: "300px"}}
dangerouslySetInnerHTML={{
__html: id || "Choose a valid Description Field"
}}
/>
</Col>
</Row>
);
}
export default Results;
Any help would be appreciated.
I have a react component that upon clicking showMore. it will load more comments. The issue im facing is that
View {showMore} More Comments
is not showing the items that are left in the array. Currently there are 7 comments in an array, and if you click show more, it will initially read show 3 more, but when i click again it says show 6 more. when it should be a lesser number than 6. It should be like show 2 more, etc. I'm quite confused on how to go about writing this logic.
What am i doing wrong
CommentList.tsx
import React, { Fragment, useState } from "react";
import Grid from "#material-ui/core/Grid";
import List from "#material-ui/core/List";
import Typography from "#material-ui/core/Typography";
import CommentItem from "./../commentItem/CommentItem";
import moment from "moment";
import OurLink from "../../../common/OurLink";
import OurSecondaryButton from "../../../common/OurSecondaryButton";
import OurModal from "../../../common/OurModal";
.....
function CommentList(props: any) {
const [showMore, setShowMore] = useState<Number>(3);
const [openModal, setOpenModal] = useState(false);
const [showLessFlag, setShowLessFlag] = useState<Boolean>(false);
const the_comments = props.comments.length;
const inc = showMore as any;
const showComments = (e) => {
e.preventDefault();
if (inc + 3 <= the_comments) {
setShowMore(inc + 3);
} else {
setShowMore(the_comments);
}
// setShowLessFlag(true);
};
........
const showMoreComments = () => {
return props.comments
.slice(0, showMore)
.sort((a, b) => a.id - b.id)
.map((comment, i) => (
<div key={i}>
<List style={{ paddingBottom: "20px" }}>
<img alt="gravatar" style={{ margin: "-10px 15px" }} src={comment.author.gravatar} width="30" height="30" />
<Typography style={{ display: "inline-block", fontWeight: 700, padding: "5px 0px" }} variant="h6" align="left">
{Object.entries(props.currentUser).length === 0 ? (
<Fragment>
<span style={{ cursor: "pointer", fontSize: "12px", fontWeight: isBold(comment) }} onClick={handleClickOpen}>
{comment.author.username}
</span>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
{openModal ? <OurModal open={openModal} handleClose={handleCloseModal} /> : null}
</Fragment>
) : (
<Fragment>
<OurLink
style={{ fontSize: "12px", fontWeight: isBold(comment) }}
to={{
pathname: `/profile/${comment.author.username}`,
}}
title={comment.author.username}
/>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</Fragment>
)}
</Typography>
<div style={ourStyle}>
<CommentItem comment={comment} user={props.user} postId={props.postId} {...props} />
<Typography style={{ fontSize: "12px" }} variant="body1" align="left">
{moment(comment.createdAt).calendar()}
</Typography>
</div>
</List>
</div>
));
};
console.log(props.comments.slice(0, showMore).length);
return (
<Grid>
<Fragment>
<div style={{ margin: "30px 0px" }}>
<OurSecondaryButton onClick={(e) => showComments(e)} component="span" color="secondary">
View {showMore} More Comments
</OurSecondaryButton>
</div>
</Fragment>
{showLessFlag === true ? (
// will show most recent comments below
showMoreComments()
) : (
<Fragment>
{/* filter based on first comment */}
{props.comments
.filter((item, i) => item)
.sort((a, b) => b.id - a.id)
.slice(0, showMore)
.map((comment, i) => (
<div key={i}>
<List style={{ paddingBottom: "20px" }}>
<img alt="gravatar" style={{ margin: "-10px 15px" }} src={comment.author.gravatar} width="30" height="30" />
<Typography style={{ display: "inline-block", fontWeight: 700, padding: "5px 0px" }} variant="h6" align="left">
{Object.entries(props.currentUser).length === 0 ? (
<Fragment>
<span style={{ fontSize: "12px", cursor: "pointer", fontWeight: isBold(comment) }} onClick={handleClickOpen}>
{comment.author.username}
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</span>
{openModal ? <OurModal open={openModal} handleClose={handleCloseModal} /> : null}
</Fragment>
) : (
<Fragment>
<OurLink
style={{ fontSize: "12px", fontWeight: isBold(comment) }}
to={{
pathname: `/profile/${comment.author.username}`,
}}
title={comment.author.username}
/>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</Fragment>
)}
</Typography>
<div style={ourStyle}>
<CommentItem comment={comment} user={props.user} postId={props.postId} {...props} />
<Typography style={{ fontSize: "12px" }} variant="body1" align="left">
{moment(comment.createdAt).calendar()}
</Typography>
</div>
</List>
</div>
))}
</Fragment>
)}
</Grid>
);
}
// prevents un-necesary re renders
export default React.memo(CommentList);
You want to show 3 more comments each time, or 1-2 items if there are less than 3 items left. So "View 3 More comments" if there are more than 3 left, or "View 1/2 More Comments" if there are only 1 or 2 left.
Or in other words cap the number of new comments shown at 3:
the minimum value of either 3 or (total number of comments - current shown comments = number of comments left).
View {Math.min(3, the_comments - inc)} More Comments
These are my tabs and tables and I want to call different functions based on tabKey when you click on the tab.
<Paper className={classes.root} style = {{paddingTop:50}}>
<Grid>
<TabSelector
displayType="button"
showTab={"Org Details"}
showCount={false}
highlightTab={true}
onClick={() => this.getTabs.bind(this)}
>
<Tab name="Org Details" tabKey="gridOrgDetails">
<p>
<Grid>
<Paper className={classes.root} style={{ paddingTop: 50 }}>
<a href="#gridOrgDetails" id="gridOrgDetails" />
<Paper style={{ backgroundColor: "#759FEB" }}>
<Typography> ORG Details </Typography>
</Paper>
<EnhancedTable
checkBoxEnabled={false}
Data={{ rows: this.getOrg(), headCells: orgDeatils }}
rowsPerPage={5}
orderBy="Call_Date_vod__c"
order="desc"
/>
</Paper>
</Grid>
</p>
</Tab>
<Tab
name="License Details"
tabKey="gridLicenseDetails"
onClick={() => this.getLicenseDetails()}
>
<p>
<Grid>
<Paper className={classes.root} style={{ paddingTop: 50 }}>
<a href="#gridLicenseDetails" id="gridLicenseDetails" />
<Paper style={{ backgroundColor: "#759FEB" }}>
<Typography> License Details </Typography>
</Paper>
<EnhancedTable
checkBoxEnabled={false}
Data={{ rows: this.getOrg(), headCells: licenseDetails }}
rowsPerPage={5}
orderBy="Call_Date_vod__c"
order="desc"
/>
</Paper>
</Grid>
</p>
</Tab>
</TabSelector>;
This is my function where I am switching keys but this seems to be not working.
Can anyone please help me?
getTabs(f){
console.log(f.tabKey)
switch(f.tabKey) {
case "gridOrgDetails":
return this.getOrgDetails();
break;
case "gridLicenseDetails":
return this.getLicenseDetails();
break;
}
}
Here's a basic representation of what you're trying to achieve jsFiddle
link
const User = (props) => <div onClick = {props.onClick}>I am user
{props.user}</div>
class App extends React.Component {
constructor(props) {
super(props)
}
getTabs(f){
switch(f) {
case "gridOrgDetails":
console.log("gridOrgDetails")
break;
case "gridLicenseDetails":
console.log("gridLicenseDetails")
break;
}
}
render() {
return (
<div>
<div >
<User user="a" onClick={this.getTabs.bind(this,"gridOrgDetails")} />
<User user="b" onClick={this.getTabs.bind(this, "gridLicenseDetails")}/>
</div>
</div>
)
}
}
ReactDOM.render(<App />, document.querySelector("#app"))
Objective
Displaying only the fields that are filled in.
Background
In my application people will first fill out the application which has fields like "early reg fee, early reg date, regular reg fee, regular reg date" and so after they fill out all the information and click "view profile" they will see all the fields whether it's filled out or not.
If the value of one of the fields is null or undefined then it would not show up in the profile.
I was trying to do this and I started of by creating a state in the constructor "this.state {value: ''}"
class CompetitionProfileView extends React.Component {
constructor(props) {
super(props);
this.state {value: ''}
this.getContactCard = this.getContactCard.bind(this);
}
getCompetitionValue(path) {
const value = _.get(this.props.competition, path);
return value ? value : '';
}
getCompetitionDateValue(path) {
const value = _.get(this.props.competition, path);
return value ? value.toDateString() : '';
}
getCompetitionTimeValue(path) {
const value = _.get(this.props.competition, path);
return value ? `${
value.getHours() - 12
}:${value.getMinutes()}` : '';
}
getContactCard(num) {
return
this.getCompetitionValue(`Information.contactFirstName${num}`) ?
<Card key={num} style={{backgroundColor: '#f9f9f9', width: '32%'}} zDepth={2}>
<CardTitle title={`${this.getCompetitionValue(`Information.contactFirstName${num}`)} ${this.getCompetitionValue(`Information.contactFirstName${num}`)}`} subtitle={`${this.getCompetitionValue('Information.contactPosition1')}`} />
<Divider/>
<CardText>
<p style={{display: 'flex', justifyContent: 'center'}}><Phone/>{`${this.getCompetitionValue(`Information.contactFirstName${num}`)}`}</p>
<p style={{display: 'flex', justifyContent: 'center'}}><Email/>{`${this.getCompetitionValue(`Information.contactFirstName${num}`)}`}</p>
</CardText>
</Card>
:
'';
}
render(actions) {
return (
<div>
<div className="profileheader" style={{display: 'flex', flexDirection: 'column'}}>
<Paper className='banner-image' style={{backgroundImage: `url(${this.getCompetitionValue('Resources.boardPicture.url')})`,backgroundSize: 'cover',width: '100%', height: '200px', backgroundPositionY: '20%'}} zDepth={3}>
{/* <br style={{lineHeight: '15'}}/> */}
</Paper>
<Paper className='text-main' style={{textAlign: 'center'}}>
<label>{this.getCompetitionValue('Information.name')}</label>
</Paper>
<Paper className='logo-image' style={{backgroundImage: `url(${this.getCompetitionValue('Resources.competitionLogo.url')})`, backgroundSize: 'cover', width: '100px', height: '100px', marginTop: '-110px', marginLeft: '3%', paddingbottom: '20px'}} zDepth={3}/>
</div>
<hr/>
<div style={{display: 'flex', justifyContent: 'space-between'}}>
<Card style={{backgroundColor: '#f9f9f9', width: '49%'}} zDepth={2}>
<RaisedButton style={{display: 'flex', justifyContent: 'center'}} primary={true} label="Application Packet" onClick={() => window.open(this.getCompetitionValue('Resources.applicationPacket.url'), '_blank')}/>
</Card>
<Card style={{backgroundColor: '#f9f9f9', width: '49%'}} zDepth={2}>
<RaisedButton style={{display: 'flex', justifyContent: 'center'}} primary={true} label="Audition Video Info" onClick={() => window.open(this.getCompetitionValue('Resources.auditionVideoInfo.url'), '_blank')}/>
</Card>
</div>
<br/>
<div className='mainbody' style={{display: 'flex', flexDirection: 'row', justifyContent: 'space-between'}}>
<br/>
<div className='rightbody' style={{display: 'flex', flexDirection: 'column', width: '60%', flexWrap: 'wrap'}}>
<Card style={{backgroundColor: '#F0EFEF'}} zDepth={2}>
<CardHeader title="About Us" />
<Divider/>
<CardText>{`${this.getCompetitionValue('Information.compBlurb')}`}</CardText>
</Card>
<br/>
<Card style={{backgroundColor: '#F0EFEF'}} zDepth={2}>
<CardHeader title="Application Information" />
<Divider/>
<CardText>
<p><b>Early Reg:</b>{` ${this.getCompetitionDateValue('Information.dueDateEarly')}`}</p>
<p><b>Early Reg Fee:</b>{` ${this.getCompetitionValue('Information.earlyDues')}`}</p>
<p><b>Regular Reg:</b>{` ${this.getCompetitionDateValue('Information.dueDateRegular')}`}</p>
<p><b>Regular Reg Fee:</b>{` ${this.getCompetitionValue('Information.regularDues')}`}</p>
<p><b>Late Reg:</b>{` ${this.getCompetitionDateValue('Information.dueDateLate')}`}</p>
<p><b>Late Reg Fee:</b>{` ${this.getCompetitionValue('Information.lateDues')}`}</p>
<p><b>Applications Due At:</b>{` ${this.getCompetitionTimeValue('Information.dueTime')}`}</p>
<p><b>Time Zone:</b>{` ${this.getCompetitionValue('Information.timeZone')}`}</p>
<p><b>Penalties:</b>{` ${this.getCompetitionValue('Information.extraFees')}`}</p>
<p><b>Hear Back Date:</b>{` ${this.getCompetitionDateValue('Information.hearbackDate')}`}</p>
<p><b>Payment Method:</b>{` ${this.getCompetitionValue('Information.paymentMethods')}`}</p>
<br/>
</CardText>
</Card>
</div>
</div>
<br/>
<div className="contactinfo" style={{display: 'flex', justifyContent: 'space-around'}}>
{[1,2,3].map((num) => this.getContactCard(num))}
</div>
<br/>
{this.props.competition.Board.length > 0 &&
<Card style={{backgroundColor: '#F0EFEF'}} zDepth={2}>
<Table >
<TableHeader adjustForCheckbox={false} displaySelectAll={false}>
<TableRow>
{ Object.keys(this.props.competition.Board[0]).map((key) => <TableHeaderColumn key={key}>{key}</TableHeaderColumn>) }
</TableRow>
</TableHeader>
<TableBody displayRowCheckbox={false}>
{this.props.competition.Board.map((row, i) => (
<TableRow key={i}>
{ Object.keys(row).map((column) => <TableRowColumn key={column}>{row[column].name ? row[column].name : row[column]}</TableRowColumn>) }
</TableRow>
))
}
</TableBody>
</Table>
</Card>
}
</div>
);
}
}
const mapStateToProps = (state) => {
return {
messages: state.messages
};
};
export default connect(mapStateToProps)(CompetitionProfileView);
You can use if statements in your render() function, like so:
render() {
if (this.props.thing1) {
return <h1>Thing 1</h1>
} else {
return (
<div className="warning">
<h2>Thing 2</h2>
</div>
)
}
}
You can even use functions in the render() function like this:
renderASmallPart() {
if (this.props.thing1) {
return <h1>Thing 1</h1>
} else {
return (
<div className="warning">
<h2>Thing 2</h2>
</div>
)
}
}
render() {
return (
<div>
<h1>My App</h1>
<h2>Here's a thing:</h2>
{this.renderASmallPart()}
</div>
)
}
You can use this to break up your large render() function into smaller functions that check what the value of their field is and only render something when the field has a non-empty value
You need to look into Conditional Rendering and only render that element when there is a value.
https://facebook.github.io/react/docs/conditional-rendering.html
https://atticuswhite.com/blog/render-if-conditionally-render-react-components/
http://devnacho.com/2016/02/15/different-ways-to-add-if-else-statements-in-JSX/
https://kylewbanks.com/blog/how-to-conditionally-render-a-component-in-react-native