I have an app which shows a welcome page with an animal's picture. Also, we can navigate to a second view, where there are two canvas, and a collapsable panel which hosts controls' inputs.

The aim of the application would be to load an image on both canvas, and let a user click on it, and in the second one, the part would be coloured and its name would be written in a textarea.

Currently, I am experimenting with React because I have recently done a project with JS, jQuery, Bootstrap, and I thought it was a mess, because we inlined scripts in HTML.

I will describe how is it organized and then I will ask you for suggest:


<!doctype html>

<html lang="es">
    <meta charset="utf-8">
    <meta name="description" content="Atlas">
    <meta name="author" content="">

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
      integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<div id="mainApp"></div>

As you can see it is just a boilerplate, and bootstrap.

My index.js React's entry point:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import '../node_modules/react-dropdown/style.css';
import {Header} from './Header'
import {Main} from './Main'
import {BrowserRouter} from 'react-router-dom'

const App = () => {

    return (


    , document.getElementById("mainApp"));

As you could see I have followed the pattern of dividing it into Header and Main, to use navigation and react router.

Header,which is a navbar:

import React from 'react';
import {Link} from "react-router-dom";
import {Navbar} from 'react-bootstrap'
import NavDropdown from "react-bootstrap/es/NavDropdown";
import Nav from "react-bootstrap/es/Nav";
import MenuItem from "react-bootstrap/es/MenuItem";

const Header = () => {
    return (

                <NavDropdown eventKey={3} title="Atlas" id="basic-nav-dropdown">
                    <MenuItem eventKey={3.1}><Link to='/'>Inicio</Link></MenuItem>
                    <MenuItem eventKey={3.2}>
                        <li><Link to='/caballo'>Caballo</Link></li>

export {Header}

Main contains paths and Components to be renderer:

import React from 'react';
import {Inicio} from "./Inicio";
import {Caballo} from "./Caballo";
import Switch from "react-router-dom/es/Switch";
import Route from "react-router-dom/es/Route";

const Main = () => {
    return (
                <Route exact path='/' component={Inicio}/>
                <Route exact path='/caballo' component={Caballo}/>

export {Main}

Inicio is the default img of the animal:

import React from 'react';
import './index.css';

const Inicio = () => {
    return (
        <img src="https://misanimales.com/wp-content/uploads/2017/09/cuarto-de-milla.jpg" alt=""/>

export {Inicio};

And Caballo is where the most of the App is:

import React from 'react';
import './index.css';
import Dropdown from 'react-dropdown';
import '../node_modules/react-dropdown/style.css';
import {ImageUpload} from "./ImageUpload";
import Panel from "react-bootstrap/es/Panel";
import Button from "react-bootstrap/es/Button";

class Caballo extends React.Component {
    state = {open: true};
    options = [
        'one', 'two', 'three'

    render() {
        return (
                    <div style={{display: "flex"}}>
                        <h3>Suba una imagen desde el ordenador, para
                        <div style={{display: "flex", justifyContent: "flex-end", width: "100%"}}>
                                onClick={() => {
                                    this.setState({open: !this.state.open});
                                    const divCanvas = document.getElementsByClassName("previewComponent");
                                    const innerCanvas = document.getElementsByTagName("canvas");
                                    if (divCanvas && innerCanvas) {
                                        const width = divCanvas[0].offsetWidth;
                                        if (!this.state.open) {
                                            const newWidth = width - 200 + "px";
                                            divCanvas[0].setAttribute("style", `width:${newWidth}`);
                                            divCanvas[1].setAttribute("style", `width:${newWidth}`);
                                            innerCanvas[0].setAttribute("style", `width:${newWidth}`);
                                            innerCanvas[1].setAttribute("style", `width:${newWidth}`);
                                        if (this.state.open) {
                                            const newWidth = width + 200 + "px";
                                            divCanvas[0].setAttribute("style", `width:${newWidth}`);
                                            divCanvas[1].setAttribute("style", `width:${newWidth}`);
                                            innerCanvas[0].setAttribute("style", `width:${newWidth}`);
                                            innerCanvas[1].setAttribute("style", `width:${newWidth}`);
                                Cerrar controles

                <article className="single-line-canvas-spaced-controls-row">
                    <section className="single-line-canvas-row">
                        < section className="spaced-column" style={{
                            backgroundColor: 'gray',
                        <section className="spaced-column" style={{
                            backgroundColor: 'yellow',
                    <div className="spaced-column" style={{
                        backgroundColor: "green"
                                    <Dropdown options={this.options} onChange={this._onSelect}
                                              placeholder="Select an option"/>
                                    <div className="row">
                                        <label><input type="checkbox" id="chbox1" value="1"/>Option 1</label>
                                        <label><input type="checkbox" id="chbox2" value="2"/>Option 2</label>
                                    <div className="row">
                                        <label><input type="checkbox" id="chbox3" value="3"/>Option 3</label>
                                        <label><input type="checkbox" id="chbox4" value="4"/>Option 4</label>

                    <div className="line-break"></div>

                <footer><textarea style={{width: "100%"}} value="Estructura:" readOnly name="herarchy"

export {Caballo}

And finally, ImageUpload, are the divs and canvas for image preview:

import React from 'react';

class ImageUpload extends React.Component {

    render() {

        const $imagePreview = (
            <div className="previewText">Por favor seleccione una imagen de su ordenador para visualizarla</div>);
        return (
            <div className="previewComponent">
                <div className="imgPreview">

export {ImageUpload};

As you see it is ugly, because the code in Caballo is too long.

  1. Control's button's onClick handler is too big: The purpose is to resize canvas when we close controls:

    • Is there an easier way to do this resize?
    • Should this handler be isolated in its file?
    • Is this the correct way to handle canvas' dimensions?
  2. CSS classNames

    First I thought that it is better to describe what it does, for example:


    Then I thought it would be better if it refers to what it is used for:


    The I mixed them both:


    What approach is the correct one?

  3. HTML/React:

    There is a React component called Header which is the navbar to navigate, and there is a header where I put the title and control's close button.

    How could I improve this naming?

  4. UI's hierarchy:

    I thought it would be correct if I isolate canvas' row as article and each canvas as section to separate them from controls.

    Is there a better way to structure the UI?

  5. Logic is scattered:

    Caballo component is too big: header is for title, and close controls button; article/section are canvas; Panel represents controls' inputs; footer is meant to be the place where dynamically we write the animal's parts' names.

    Could we divide or simplify this Component?

In addition, the default page looks:

enter image description here

Canvas' page with controls opened:

enter image description here

Controls closed:

enter image description here


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.