#reactjs #redux #react-redux #google-cloud-firestore #react-redux-firebase
#reactjs #сокращение #реагировать-redux #google-облако-firestore #react-redux-firebase
Вопрос:
-
Я использую firestoreConnect () для синхронизации моих данных из firestore с redux.
-
Я получаю массив объектов employee обратно из firestore через state.firestore.ordered
-
сотрудник формируется следующим образом:
{ id: 'XtVe567...', name: { first: 'John', last: 'Doe' } }
-
В mapStateToProps мне нужно преобразовать форму этих данных, прежде чем возвращать их и передавать в компонент через props
function mapStateToProps(state) { const schedules = state.firestore.ordered.employees .map(employee => ({ id: employee.id, name: { first: employee.name.first, last: employee.name.last }, schedule: [null, null, null, null, null, null, null] })); const rota = { id: null, date: moment(), notes: null, events: [null, null, null, null, null, null, null], published: null, body: schedules }; return {rota} }
-
Это приводит к: TypeError: не удается прочитать свойство ‘map’ из undefined
- Я знаю, это потому, что выборка данных является асинхронной, и в момент времени, когда я сопоставляю state.firestore.ordered.employees свойство employees === undefined, которое не может быть повторено
Итак, мой вопрос в том, как вы выполняете такого рода преобразование данных с помощью асинхронных данных? Есть ли способ каким-либо образом приостановить выполнение mapStateToProps и дождаться возврата данных ПЕРЕД отображением поверх них?
Заранее спасибо и извините, если этот вопрос непонятен, я публикую его впервые.
Ответ №1:
Чтобы быстро заставить это работать, вы могли бы просто сделать что-то вроде:
function mapStateToProps(state) {
const employees = state.firestore.ordered.employees;
const schedules = employees
? employees.map(employee => ({
id: employee.id,
name: {
first: employee.name.first,
last: employee.name.last
},
schedule: [null, null, null, null, null, null, null]
}))
: undefined;
const rota = {
id: null,
date: moment(),
notes: null,
events: [null, null, null, null, null, null, null],
published: null,
body: schedules
};
return { rota }
}
Затем в вашем компоненте вы можете проверить наличие атрибута schedules объекта rota и, если он все еще не определен, отобразить что-нибудь, указывающее, что данные еще не загружены.
Тем не менее, использование такой сложной логики в mapStateToProps
для меня является антипаттером. Вы можете использовать шаблон селектора, чтобы сделать ваш код более организованным.
Ответ №2:
Ваш компонент должен реагировать на изменения в базовых данных. Итак, вы можете отобразить что-то вроде этого:
getSchedules(emps) {
return emps.map(employee => <SomeEmployeeRenderingComponent emp={employee} /> );
}
render() {
return (
<div>{this.getSchedules(this.props.employees).bind(this)}</div>
)
}
и mapstatetoprops становится:
function mapStateToProps(state) {
const rota = {
id: null,
date: moment(),
notes: null,
events: [null, null, null, null, null, null, null],
published: null,
employees: state.firestore.ordered.employees
};
return rota
}