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)}
/>