#javascript #reactjs #typescript
#javascript #reactjs #typescript
Вопрос:
Возможно ли написать универсальный компонент? который получает некоторый объект с похожими данными (например: идентификатор, заголовок, текст, дата) и отображает его. Но все объекты имеют разные ключевые имена. Например, три объекта, все они имеют идентификатор, заголовок, текст и дату:
obj1 {id: 1, textVar: 'textString1', titleVar: 'titleString1', date1: '2000-10-10'}
obj2 {id: 2, title2: 'titleString2', someDate: '2001-11-11', otherTextVar: 'textString2'}
obj3 {id: 3, otherText3: 'textString3', otherDate: '2000-10-10', newsTitle: 'titleString3'}
Возможно ли написать универсальный компонент, который может работать с любым из объектов?
interface UCompProps {
id: number,
title: string,
text: string,
date: string,
},
}
const UComponent: React.FC<UCompProps> = (props) => {
const { id, title, text, date } = props;
return (
<>
<div>{id}</div>
<div>{title}</div>
<div>{text}</div>
<div>{date}</div>
</>
)
}
export default UCompProps
Понятия не имею, как это сделать. Любой совет, как это сделать?
Комментарии:
1. Да, вы могли бы использовать Object.entries для реквизитов, но мне это не кажется правильным.. Приведенный выше код с таким же успехом может означать, что вы только что отправили массив или объект в 1 prop.
2. Если порядок идентификаторов, заголовка, текста, даты одинаковы, вы можете легко использовать Object.values()
3. Нет, у него не тот же порядок. вся проблема в том, что я не могу знать, что есть что. Заголовок и текст — это строки, и они могут иметь любые ключевые имена: (
4. Есть ли шанс, что вы можете контролировать, как генерируются входные модули?
5. Серверная часть написана другими людьми, и есть некоторые очень похожие данные. Мне нужно создать компонент, который выводит предварительный просмотр для этих данных. (например: список новостей, список статей, список продаж и другие.)
Ответ №1:
Если вы знаете структуры всех объектов, то вы можете сопоставить массив этих объектов.
// in parent:
return (
<div>
{arrayOfobjects1
.map(obj1=>({
id:obj1.id, title:obj1.titleVar , text:obj1.textVar, date: obj1.date1
}))
.map(props=><Ucomponent key={props.id} {...props} />)
}
</div>
)
А также вы можете определить, что функции отображения для каждого типа объектов:
// in parent:
const mapper1 = object1 => ({id:obj1.id, title:obj1.titleVar, text:obj1.textVar, date: obj1.date1});
return (
<div>
{arrayOfobjects1
.map(mapper1)
.map(props=><Ucomponent key={props.id} {...props} />)
}
</div>
)
Или вы можете отобразить их все вместе после сопоставления каждого массива
const arrayToRender = [...arr1.map(mapper1), ...arr2.map(mapper2), ...arr3.map(mapper3)];
Ответ №2:
Если порядок идентификаторов, заголовка, текста, даты одинаковы, вы можете легко использовать Object.values()
const UComponent = (props) => {
const { id, title, text, date } = props;
return (
<div>
<div>ID: {id}</div>
<div>TITLE: {title}</div>
<div>TEXT: {text}</div>
<div>DATE: {date}</div>
<br/>
</div>
)
}
const App = (props) => {
const { data } = props;
const components = data.map((obj) => {
const [id, title, text, date] = Object.values(obj);
return <UComponent id={id} title={title} text={text} date={date} />;
});
return (
<div>
{components}
</div>
)
}
const objs = [
{id: 1, titleVar: 'titleString1', date1: '2000-10-10', textVar: 'textString1'},
{id: 2, title2: 'titleString2', someDate: '2001-11-11', otherTextVar: 'textString2'},
{id: 3, newsTitle: 'titleString3', otherDate: '2000-10-10', otherText3: 'textString3'},
];
ReactDOM.render(
<App data={objs} />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>