1. Статические данные. Зачем они определяются каждый render? Их можно вынести за пределы компонента:
const paths = [ ... ];
class Menu extends Component { ... }
А по-хорошему генерировать роуты и переключать страницы по одним и тем же данным:
import routes from './routes';
/* ... */
<Switch>
{routes.map(route => (
<Route
exact={route.isExact}
path={route.path}
component={route.component}
/>
)}
</Switch>
2. По какой логике используете ключевые слова const и let? Используйте const для всех переменных которые не переопределяются в коде, а let только для тех, которые переопределяются. Это заметно снижает когнитивную нагрузку с читающего код.
3. Конструкции вроде:
let
isPrev = currPathIndex !== 0,
isNext = currPathIndex !== paths.length - 1;
часто вызывают проблемы при рефакторинге. Лучше не экономить на спичках и писать ключевые слова для каждой строки:
const hasPrev = currPathIndex !== 0; // (1)
const hasNext = currPathIndex !== paths.length - 1; // (2)
В такой код проще вносить изменения и ему не страшны ошибки вроде пропущенной запятой или точки с запятой вместо запятой, что может сэкономить время.
(1), (2) - обратите внимание, что я заменил префикс is на has, что правильней. Для булевых переменных помимо is, можно использовать следующие префиксы is, has, should и подобные. Примеры:isVisible
hasChildren
shouldShowCloseButton
4. Если используете много ключей из state и props можно сделать деструктуризацию:
const { isOpen } = this.state;
5. Don't repeat yourself. Код который вы используете многократно старайтесь выносить в отдельные компоненты:
<Link className="next_btn" style={ this.state.isOpen ? {visibility: 'hidden'} : null} to={paths[currPathIndex + 1].link}>
<span>{ paths[currPathIndex + 1].title }</span>
</Link>
Его можно переписать компонентом с примерно таким интерфейсом:
<NavButton prev isVisible={!isOpen} path={prevPath} />
6. Зачем тернарки там где лучше подойдет &&?
{isOpen && this.renderСloseBtn()} // (1)
{hasPrev && <NavButton prev isVisible={!isOpen} path={prevPath} />}
{hasNext && <NavButton next isVisible={!isOpen} path={nextPath} />}
(1) - обратите внимание, что рендер кнопки вынесен в отдельный метод, так она будет создаваться только тогда, когда она нужна. В вашем же коде она определяется даже тогда когда не добавляется на страницу.
Используйте тернарный оператор в render, там где есть альтернативный вариант:
{isFetching ? <Preloader /> : <Content data={data} />}
Но не используйте вложенных:
{isSignedIn ? isMobile ? <UserMenuMobile /> : <UserMenuDesktop /> : <MainMenu /> }
Лучше так:
{isSignedIn ? this.renderUserMenu() : <MainMenu /> }
где this.renderUserMenu:
renderUserMenu() {
return this.props.isMobile ? <UserMenuMobile /> : <UserMenuDesktop />;
}
7. Старайтесь не писать избыточных конструкций:
class Menu extends Component {
constructor(props) {
super(props);
this.state = {
isOpen: false,
};
}
}
При использовании прессета stage-0, create-react-app, jsfiddle и прочих библиотек/бойлерплейтов/сервисов, использующих плагин babel-plugin-transform-class-properties, достаточно:
class Menu extends Component {
state = {
isOpen: false,
};
}