I have a a component that needs to check for multiple options and return based on those options. Therefore I have created an outside function that is called in my component return statement to determine the format that will be returned:
render() {
const { policy } = this.props;
let deployment = policy.Deployment;
let value = policy.value;
let policyLegend = deployment.policyLegend;
let policyObj = this.valueToPolicy(policyLegend, value);
console.log(policyObj);
if(policy.name == "SP4") {
policyLegend[1].values = this.formatSp4Firmware(policyLegend[1]);
return (
<div>
<Form onSubmit={ (event) => this.handleSubmit(event, this.props) }>
{
policyLegend.map((policy) => {
return (
<div key={ policy.id }>
<h3>{ policy.displayName }</h3>
{ this.renderSp4Policies(policy) }
</div>
);
})
}
<Button name={ 'Submit' } type='submit'>Submit</Button>
<Button onClick={ this.props.onCancel }>Cancel</Button>
</Form>
</div>
)
}
}
<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>
renderSp4Policies(policy) {
if(policy.displayName == "Firmware Options") {
let firmwareDropdownNames = this.formatFirmawareDropdownNames(policy);
let toggles = policy.values[0][Object.keys(policy.values[0])];
let toggleOptions = []
Object.keys(toggles).map(toggle => {
if(typeof(toggles[toggle]) == "boolean"){
var obj = {};
obj[toggle] = toggles[toggle];
toggleOptions.push(obj);
}
})
return (
toggleOptions.map(toggleOption => {
let toggleName = Object.keys(toggleOption).toString();
return (
<Form.Field key={ toggleName }>
<label>{ toggleName }</label>
<Checkbox toggle />
</Form.Field>
)
})
)
} else {
return (
policy.values.map(value => {
return(
<Form.Field key={ value.name }>
<label>{ value.displayName || value.name }</label>
<Checkbox toggle />
</Form.Field>
)
}
)
)
}
}
<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>
EDIT
I have applied some of the answers given with moderate success.
Within renderSp4Policies
what is being returned in the else
statement displays, but the beginning if(policy.displayName == "Firmware Options")
returns nothing.
Appreciate all advice, thank you in advance!
JSX stands for JavaScript XML, a coding standard that allows you to use JavaScript expressions and other HTML features inline. Using JSX, you can create a function and return a set of JSX elements to a variable, and that variable used is to render the elements inside the render () function in React.
The expression can be a React variable, or property, or any other valid JavaScript expression. JSX will execute the expression and return the result: Execute the expression 5 + 5:
JSX is an extension of the JavaScript language based on ES6, and is translated into regular JavaScript at runtime. Get Certified! Complete the React modules, do the exercises, take the exam and become w3schools certified!! With JSX you can write expressions inside curly braces { }.
Or you can return HTML inside JavaScript logic (such as if-else cases): render () { if (true) { return <p>YES</p>; } else { return <p>NO</p>; } } I won't go into further details of JSX, but make sure that you consider the following rules while writing JSX:
Your map
function doesn't return anything:
policy.values.map(value => {
<Form.Field key={ value.name }>
<label>{ value.displayName || value.name }</label>
<Checkbox toggle />
</Form.Field>
}
When using an arrow function block {}
you should add an explicit return
statement:
policy.values.map(value => {
return(<Form.Field key={ value.name }>
<label>{ value.displayName || value.name }</label>
<Checkbox toggle />
</Form.Field>)
}
Edit
As a followup to your comment.
As for the first if
statement, don't use a forEach
, use a map
. same as you did in the second if
statement (don't forget the return
!)
renderSp4Policies(policy) {
if (policy.displayName == "Firmware Options") {
let toggles = policy.values[0][Object.keys(policy.values[0])];
Object.keys(toggles).forEach(toggle => {
if (typeof (toggles[toggle]) !== "boolean") {
delete toggles[toggle];
}
})
return (
Object.keys(toggles).map(toggle => {
return (
<Form.Field key={toggle}>
<label> {toggle} </label>
<Checkbox toggle />
</Form.Field>
);
})
)
} else {
return (
policy.values.map(value => {
<Form.Field key={value.name}>
<label>{value.displayName || value.name}</label>
<Checkbox toggle />
</Form.Field>
})
);
}
}
It seems like many people already did really well to help you fix your problem and explain it with details. But don't forget to follow the new concept of Component-Based architecture that React has introduced. So as a best practice you can write it this way:
import React, {Component} from "react";
import Sp4Policies from "./sp4Policies";
class MyComponent extends Component {
render() {
const { policy } = this.props;
let deployment = policy.Deployment;
let value = policy.value;
let policyLegend = deployment.policyLegend;
let policyObj = this.valueToPolicy(policyLegend, value);
console.log(policyObj);
if(policy.name == "SP4") {
policyLegend[1].values = this.formatSp4Firmware(policyLegend[1]);
return (
<div>
<Form onSubmit={ (event) => this.handleSubmit(event, this.props) }>
{
policyLegend.map((policy) => {
return (
<div key={ policy.id }>
<h3>{ policy.displayName }</h3>
<Sp4Policies policy={policy} />
</div>
);
})
}
<Button name={ 'Submit' } type='submit'>Submit</Button>
<Button onClick={ this.props.onCancel }>Cancel</Button>
</Form>
</div>
)
}
}
}
and a separate file:
import React, {Component} from "react";
class Sp4Policies extends Component {
render() {
const policy = this.props.policy;
if (policy.displayName == "Firmware Options") {
return (
policy.values.map(value => (
<Form.Field key={ value.name }>
<label>{ value.displayName || value.name }</label>
<Checkbox toggle />
</Form.Field>
))
);
}
return (
let toggles = policy.values[0][Object.keys(policy.values[0])];
Object.keys(toggles).forEach(toggle => {
if(typeof(toggles[toggle]) !== "boolean"){
delete toggles[toggle];
}
})
Object.keys(toggles).map(toggle => {
return(
<Form.Field key={ toggle }>
<label> { toggle } </label>
<Checkbox toggle />
</Form.Field>
);
})
);
}
}
export default Sp4Policies;
this makes your code clean and it ensures separation of concerns between your components. And of course you can still separate it even further.
I run into this quite a bit and didn't just realize why this works until now. In your renderSp4Policies
function, you're mapping through keys on the second line that has Object.keys(toggles).forEach(toggle => {
. Inside that block you're returning elements and that instruction you're running is keeping track of that and generating an array. Once it's done, you're not doing anything with the array, so you have to add a return
statement so the function returns the generated array of JSX elements:
return Object.keys(toggles).map(toggle => {
return(
<Form.Field key={ toggle }>
<label> { toggle } </label>
<Checkbox toggle />
</Form.Field>
);
});
Also as Sag1v says, the line that has policy.values.map
, you're not returning inside that loop. So you have to change:
policy.values.map(value => (
return (
<Form.Field key={ value.name }>
<label>{ value.displayName || value.name }</label>
<Checkbox toggle />
</Form.Field>
);
));
Edit
After our discussion in chat, I wanted to update my answer to reflect the proper changes.
The first Object.keys
call that determines which keys should be saved and which shouldn't wasn't returning new data after every iteration so it was just making an empty array. forEach
was also being used but that doesn't return a new array. After changing forEach
to map
and adding some return statements, it would create a new array so the second loop that follows would be able to run:
var toggleOptions = Object.keys(toggles).map(toggle => {
if (typeof (toggles[toggle]) !== "boolean") {
return delete toggles[toggle];
}
return toggles[toggle];
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With