I'm trying to make a dynamic React loader similar to
Any pointers are much appreciated.
Here is my simplified code:
import React from 'react';
function H1(props){return <h1>H1-{props.index}</h1>}
function H2(props){return <h2>H2-{props.index}</h2>}
function H3(props){return <h3>H3-{props.index}</h3>}
export default class DynamicPageTest extends React.Component {
constructor(props) {
super(props);
this.componentMapping = {
H1:H1,
H2:H2,
H3:H3,
};
this.state = {
componentNames: ["H1","H2","H3","H2","H3"]
};
}
moveComponentUp(index){
this.swapComponents(index,index-1)
}
moveComponentDown(index){
this.swapComponents(index,index 1)
}
swapComponents(indexA,indexB){
let newComponentNames = this.state.componentNames.slice();
let temp = this.state.componentNames[indexB];
newComponentNames[indexB] = newComponentNames[indexA];
newComponentNames[indexA] = temp;
this.setState({componentNames: newComponentNames});
alert(newComponentNames)
}
render() {
let pageComponents = []
this.state.componentNames.forEach((componentName, index) => {
let callbacks = {
moveComponentUp: ()=>{this.moveComponentUp(index)},
moveComponentDown: ()=>{this.moveComponentDown(index)}
}
const Component = this.componentMapping[componentName];
let newComponent = <ComponentWrapper key ={`${componentName}`} index = {index} componentCount = {this.state.componentNames.length} callbacks = {callbacks}>
<Component index = {index}/>
</ComponentWrapper>
pageComponents.push(newComponent)
});
return (
<div >
{pageComponents}
</div>
);
}
}
class ComponentWrapper extends React.Component {
constructor(props) {
super(props);
this.children = props.children;
this.state = {
index:props.index,
callbacks: props.callbacks,
componentCount:props.componentCount
};
}
render() {
return (
<div style = {{display: "flex", flexDirection: "column", border:"1px solid black",margin:"10px 0px"}}>
<div style={{display: "flex", flexDirection: "row", position:"relative"}}>
{this.state.index}{this.children}
<div style={{display: "flex", flexDirection: "column",position: "absolute", right: "0"}}>
<div style={{height:"100%",display:"flex",flexDirection:"column",justifyContent:"baseline"}}>
{this.state.index != 0 && <button onClick = {this.state.callbacks.moveComponentUp}>Move Up</button>}
{this.state.index != this.state.componentCount - 1 && <button onClick = {this.state.callbacks.moveComponentDown}>Move Down</button>}
</div>
</div>
</div>
</div>
)
};
}
CodePudding user response:
This is because you are setting this.state.index
from the props.index
in the constructor. This is not a mistake per se. But, when the component is rerendered, the state.index
is set once and not updated anymore.
If you want it to be updated, use the index from the props
directly.
...
{this.props.index}{this.children}
<div style={{display: "flex", flexDirection: "column",position: "absolute", right: "0"}}>
<div style={{height:"100%",display:"flex",flexDirection:"column",justifyContent:"baseline"}}>
{this.props.index != 0 && <button onClick = {this.state.callbacks.moveComponentUp}>Move Up</button>}
{this.props.index != this.state.componentCount - 1 && <button onClick = {this.state.callbacks.moveComponentDown}>Move Down</button>}
</div>
</div>
...