问题
I'm just wanted to know if there is a best practice approach to rendering an element with ReactJS dynamically
Consider these scenarios:
(1) Parameter Factory component:
A parameterised factory component whose job is to render a component based on a string parameter, is there a way of doing so without having to revert to React.createElement?
<pre><code>// The following doesn't work
class Quiz extends React.Component{
constructor (props){
super (props);
this.state = {
questionText: '',
correctAnswer: [],
assetType: ['DragNDrop','MultipleChoice','MatchPairs']
}
}
render(){
const { questionText, correctAnswer } = this.state;
return <{this.state.assetType[this.props.typeIndex] />;
}
}
</code></pre>
(2)Dynamic HTML tags:
Render a different HTML header tag based on an integer input. For this, I initially tried to use Template strings but had to resort to conditional rendering.
<pre><code>// No joy with Template strings
render (){
<{`h${this.state.headerSize}`}>
{this.state.headerText}
</ {`h${this.state.headerSize}`}>
}
I like using JSX, and it would be nice to be able to use dynamic element names with it for consistency.
I'm also aware that:
assetType: ['DragNDrop','MultipleChoice','MatchPairs']
can be stored as:
assetType: [<DragNDrop />,<MultipleChoice />, <MatchPairs />]
which will work.
One issue I have with the array of JSX elements is how to store the these JSX elements in a DB? I'm guessing I'd have to store them as Strings
but then how to use them when pull backed form the DB?
Can anyone suggest any working and best practice approaches to these issues?
回答1:
Regarding dynamic HTML tags:
EDIT:
As the docs suggest, Dynamic types can be used at runtime if first assign to a capitalised variable first:
class Quiz extends React.Component {
constructor(props) {
super(props);
this.state = {
questionText: '',
correctAnswer: [],
assetType: ['DragNDrop', 'MultipleChoice', 'MatchPairs']
}
}
render() {
const ElementNameStartsWithCapitalLetter = this.state.assetType[0];
// ^ -- capital letter here, ensure this works when used in JSX
return <ElementNameStartsWithCapitalLetter />;
}
}
This is due to the fact that User Defined JSX Components Must BE Capitalized.
PREVIOUS SOLUTIONS:
Using React.createElement:
class Quiz extends React.Component{
constructor (props){
super (props);
this.state = {
questionText: '',
correctAnswer: [],
assetType: ['DragNDrop','MultipleChoice','MatchPairs']
}
}
render(){
const { questionText, correctAnswer } = this.state;
{React.createElement(
[this.props.typeIndex],
{...questionText, ...correctAnswer}
);}
}
}
Using conditional rendering:
// Conditional rendering works, but yuck!
// One condition per state works
// <b>but can be unnecessarily verbose</>
getHeader() {
switch(this.state.headerSize){
case 1:
return <h1>{ this.state.headerText }; <h1>
case 2:
return <h2>{ this.state.headerText }<h2>
.
.
.
default:
return null;
}
}
render (){
return { this.getHeader() }; // bound correctly in constructor of course :)
}
来源:https://stackoverflow.com/questions/41634517/dynamic-jsx-element-tag-names