Home > Mobile >  Refactoring code that controls which component gets displayed
Refactoring code that controls which component gets displayed

Time:05-21

Hey so I'm working on a project where I need to display different components when users click on a button. Can you see if there's anyway I can reactor the code to be cleaner? I'm using react/next.js for the frontend.

Setting up useState to control which component is viewed. Using Boolean array as input

const [views, setViews] = useState([true, false, false])

Displaying the buttons that users will click to select view

<nav className='flex flex-row justify-end'>
   <button
      type='button'
      className={`mainBtn p-2 mr-2`   (views[0] ? ' active' : '')}
      onClick={() => setViews([true, false, false])}
   >Create New Order</button>
   <button
      type='button'
      className={`mainBtn p-2 mr-2`   (views[1] ? ' active' : '')}
      onClick={() => setViews([false, true, false]) }
   >View orders</button>
   <button
      type='button'
      className={`mainBtn p-2 mr-2`   (views[2] ? ' active' : '')} 
      onClick={() => setViews([false, false, true]) }
   >Manage account</button>
   <button 
      type='button'
      className={`mainBtn p-2 mr-2`}
      onClick={() => signOut() }
   >Sign Out</button>
</nav>

Using conditional rendering to display the desired components

{views[0] && <DisplayCreateNewOrder id={session.user.customer.locationID}/>}
{views[1] && <DisplayPendingOrders id={session.user.customer.locationID}/>}
{views[2] && <DisplayAccount customer={session.user.customer}/>}

any feedback is much appreciated. Also, the last two code blocks are wrapped in a div element with some tailwinds classes.

Thanks

CodePudding user response:

First, from your code it is evident that only one view can appear at any given time. This means that instead of holding 3 booleans, you can just hold the id/name of the view that is currently active:

const {CreateNewOrder, ViewOrders, ManageAccount} = {'create', 'view', 'account'};
const [activeView, setActiveView] = useState(CreateNewOrder);

Then you can use a function to make the conditional more readable:

const isViewActive = view => activeView === view;

And you would use it like this:

{isViewActive(ManageAccount) && <DisplayAccount id={session.user.customer}/>}

There's probably more consolidation you could do by having all three views accept customer instead of some accepting only the ID.

CodePudding user response:

You can simplify the state as only one view is visible at a time, there is no need to store three boolean variables. Full example - Codesandbox.

Store views in an enum/constant -

const Views = Object.freeze({
  Create: "Create",
  View: "View",
  Manage: "Manage"
});

State can simply be current active view, very simple -

const [view, setView] = useState(Views.View);

Buttons can be refactored into one reusable component -

const LinkButton = ({ text, isActive, onClick }) => {
    return (
      <button
        type="button"
        className={`mainBtn p-2 mr-2`   (isActive ? " active" : "")}
        onClick={onClick}
      >
        {text}
      </button>
    );
  };

Then used as

<LinkButton
  text="View Orders"
  isActive={view === Views.View}
  onClick={() => setView(Views.View)}
/>
  • Related