How to dynamically generate a menu in react conditional rendering

I have this react class that has 3 options for rendering. 1-upload an image, 2- select and view that image and 3 - get some result upon selecting a provider and posting to an api endpoint.

For each option i want to create a menu button/s that only renders in that phase of the process. So in this code below i have created methods for each button and each render phase 'viewMode' and i populate a nav array with these buttons. Which is supposed to be rendered in the menu() method. Right now the buttons show one step behind in rendering phase.

I know i can do this another way ie with viewMode=='selection'?x:y but i am curious to know how i can get this working. Below is the code. It's long but should be quite easy to follow.

import React, { createRef } from "react";
import Nav from 'react-bootstrap/Nav';
import { connect } from 'react-redux';
import Upload from '../Upload';
import { actionUpdateViewMode } from '../redux/actions/actions';

const mapStateToProps = (state) => {
    return {
        viewMode: state.viewMode,
    };
};
const mapDispatchToProps = (dispatch) =>
({
    uvm: (mode) => dispatch(actionUpdateViewMode(mode.viewMode))
});
class DoStuff extends React.Component {
    constructor(props) {
        super(props);
        this.selRef = createRef();
        this.nav = [];
        this.postToApi = this.postToApi.bind(this);
        this.goToSelection = this.goToSelection.bind(this);
        this.goToUpload = this.goToUpload.bind(this);
    }
    goToUpload() {
        this.props.uvm({ viewMode: 'upload' });
    }
    goToSelection() {
        this.props.uvm({ viewMode: 'selection' });
    }
    render() {
            return (
                <div>
                    <div className="col-md app-title">
                        <h2> {process.env.REACT_APP_TITLE}</h2>
                    </div>
                    {this.menu()}
                    <div className="container">
                        {this.chooseView()}
                    </div></div>
            );
    }
    menu() {
        return (
            <Nav justify variant="tabs">
                {this.nav.map(nav => (
                    nav
                ))}
            </Nav>
        );
    }
  providerSelector() {
        return (
            <Nav.Item>
                <select ref={this.selRef} onSelect={this.setClient}>
                    <option value="f">First</option>
                    <option value="s">Second</option>
                </select>
            </Nav.Item>
        );
    }
    postButton() {
        return (
            <Nav.Item>
                <button onClick={this.postToApi}>Post</button>
            </Nav.Item>
        );
    }
    uploadButton() {
        return (
            <Nav.Item>
                <button onClick={this.goToUpload}>To Upload</button>
            </Nav.Item>
        );
    }
    chooseView() {
        switch (this.props.viewMode) {
            case 'result':
                return this.result();
            case 'selection':
                return this.selection();
            case 'upload':
                return this.upload();
            default:
            case 'upload':
                return this.upload();
        }
    }
    upload() {
        this.nav = [];
        this.nav.push(this.uploadButton());
        return (
            <div className="row">
                <div className="col-md-5"></div>
                <div className="col-md-7">
                    <Upload />
                </div>
            </div>
        );
    }
    selection() {
        let resp = this.props.model;
        this.nav = [];
        this.nav.push(this.providerSelector());
        this.nav.push(this.postButton());
        this.nav.push(this.uploadButton());
        return (
            <div className="row">
                <div className="col-md">
                    <p>Your selection</p>
                </div>
            </div>
        );
    }
    result() {
        this.nav = [];
        this.nav.push(this.uploadButton());
        return (
            <div className="row">
                <div className="col-md">
                   <p>Here is the result</p>
                </div>
            </div>
        );
    }
    postToApi() {
   // populate some values 
        fetch(url, {
            method: 'POST',
            body: formData
        })
            .then(response => response.json())
            .then(data => {
                console.log(data);
                this.setState({ model: data });
                this.props.uvm({ viewMode: 'result' });
            })

            .catch(error => {
                console.log('Error:', error);
                this.props.uvm({ viewMode: 'error' });
            });
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(DoStuff);

Thank you in advance for any suggestions.



Read more here: https://stackoverflow.com/questions/65701950/how-to-dynamically-generate-a-menu-in-react-conditional-rendering

Content Attribution

This content was originally published by Amir at Recent Questions - Stack Overflow, and is syndicated here via their RSS feed. You can read the original post over there.

%d bloggers like this: