React: формат json-а от backend не позволяет провести рендеринг списком
Есть страница, на которой рендерится 10 одинаковых компонентов таблицы с разными данными. Таблица принимает пропсы типа data, page, perPage и т.п. и все эти пропсы необходимо хранить в состоянии самой страницы. Сейчас состояние моей страницы выглядит примерно вот так:
{
table1Data: [...],
table1Page: 1,
table1PerPage: 10,
table2Data: [...],
table2Page: 3,
table2PerPage: 25,
table3Data: [...],
table3Page: 100,
table3PerPage: 30,
....
}
...что мне очень не нравится и архитектурно выглядит ужасно.
Вопрос: Как правильно создавать страницы, на которых планируется рендерить одинаковые компоненты с разными пропсами (данными) при условии что сами данные должны передаваться от родительского компонента?
Какое решение мне не подходит: Превратить стейт выше в нечто типа...
{
table1: {
data: [...],
page: 1,
perPage: 10,
},
table2: {
data: [...],
page: 1,
perPage: 10,
},
table3: {
data: [...],
page: 1,
perPage: 10,
},
...
}
Также мне не хочется делать отдельные компоненты из каждой таблицы и хранить состояние в них.
Какие идеи имею на данный момент: Сделать что-то типа компонента-обертки, который будет принимать "локальное состояние" в качестве одного из пропсов, а также функции для изменения этого состояние. Например:
<LocalState
state={{
data: [...],
page: 1,
perPage: 10,
}}
handlers={(setLocalState) => ({
setData: () => {...},
setPage: () => {...},
setPerPage: () => {...},
})}
>
{(state, handlers) => <Table {...state} {...handlers} />}
</LocalState>
В общем, подскажите, как бы вы решили такую проблему и как по-вашему архитектурно правильно ее решать?
Ответы (1 шт):
А почему бы просто не превратить одно в другое, к чему такие сложности?
Адаптер — структурный шаблон проектирования, предназначенный для организации использования функций объекта, недоступного для модификации, через специально созданный интерфейс.
(function() {
const capitalize = (s) => s[0].toUpperCase() + s.slice(1);
const wrap = (obj) => Object.entries(obj)
.reduce((acm, [key, v]) => Object.entries(v)
.map(([k, v]) => [capitalize(k), v])
.reduce((acm, [k, v]) => ({...acm, [key + k]: v}), acm),
{});
console.log(wrap({
table1: {
data: ['...'],
page: 1,
perPage: 10,
},
table2: {
data: ['...'],
page: 1,
perPage: 10,
},
table3: {
data: ['...'],
page: 1,
perPage: 10,
},
}));
})();
Соответственно, то же преобразование, но в обратную сторону
(function() {
const lowerize = (s) => s[0].toLowerCase() + s.slice(1);
const getProp = (str) => {
const {index} = /[A-Z]/g.exec(str);
return [str.slice(0, index), lowerize(str.slice(index, str.length))];
};
const unwrap = (obj) => Object.entries(obj)
.reduce((acm, [k, v]) => {
const [key, prop] = getProp(k);
if (key in acm) {
acm[key][prop] = v;
} else {
acm[key] = {};
acm[key][prop] = v;
}
return acm;
}, {})
console.log(unwrap({
table1Data: ['...'],
table1Page: 1,
table1PerPage: 10,
table2Data: ['...'],
table2Page: 3,
table2PerPage: 25,
table3Data: ['...'],
table3Page: 100,
table3PerPage: 30,
}));
})();

