Home > Mobile >  How do I keep correct indexing while dynamically rendering React components?
How do I keep correct indexing while dynamically rendering React components?

Time:12-18

I'm trying to make a dynamic React loader similar to enter image description here

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>
    ...
  • Related