Вынесите ClientType в независимый модуль, сервис пусть принимает clientId и возвращает уже разобранные данные. Компонент должен управлять загрузкой, ошибкой и отменой устаревшего запроса.
Оптимизация и реорганизация React‑компонентов
Вынесите ClientType в независимый модуль, сервис пусть принимает clientId и возвращает уже разобранные данные. Компонент должен управлять загрузкой, ошибкой и отменой устаревшего запроса.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
В рамках задачи необходимо выполнить рефакторинг кода React‑приложения, улучшив структуру и отделив запросы к API от компонентов. Приведённые ниже файлы представляют текущую реализацию.
// dataService.js
import { ClientType as _ClientType } from './root';
export function getData(state) {
const response = fetch('/api/companies', {
method: 'POST',
body: JSON.stringify({
id: state.client.id,
type: _ClientType.company
})
});
return response;
}
export const ClientType = _ClientType;
// component.jsx
import * as React from 'react';
import { getData, ClientType } from './dataService';
function Component(props) {
const { store } = props;
const [items, setItems] = React.useState([]);
React.useEffect(() => {
(async () => {
const response = getData(store.getState());
const data = await (await response).json();
setItems(data.items);
})();
}, []);
return (
<div>
{items.map((item) => (
<div className={`item item_type_${item.type}`} key={item.id}>
{item.type === ClientType.person ? (
<span>{item.name}</span>
) : (
<span>Компания {item.id}</span>
)}
<button onClick={() => { console.log(item.id); }}>choose</button>
</div>
))}
</div>
);
}
export default Component;
// root.jsx
import * as React from 'react';
import Component from './component';
import store from './store';
export const ClientType = {
'company': 'company',
'person': 'person',
};
function Root() {
return (
<Component store={store} />
);
}
export default Root;
// app.jsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import Root from './root';
ReactDOM.render(<Root />, document.querySelector('#app'));
Ответ
Вынесите ClientType в независимый модуль, сервис пусть принимает clientId и возвращает уже разобранные данные. Компонент должен управлять загрузкой, ошибкой и отменой устаревшего запроса.
Сейчас dataService импортирует root, root — component, а component — dataService: это ненужная циклическая зависимость. Передача всего store.getState() также связывает сетевой слой со структурой хранилища.
async function getCompanies(clientId, signal) {
const response = await fetch('/api/companies', {
method: 'POST', signal,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id: clientId, type: 'company' })
});
if (!response.ok) throw new Error('Ошибка загрузки');
const data = await response.json();
return data.items;
}
Получайте clientId через реактивную подписку на store и ставьте его в зависимости эффекта. В cleanup отменяйте запрос и не применяйте устаревший результат. Для session API добавьте предусмотренную сервером CSRF-защиту; сам заголовок JSON её не заменяет. Инициализацию React обновляйте под фактическую версию проекта, а не как часть изменения бизнес-логики.