Изменения стора redux не вызывает рендер компонента
Использую redux-toolkit, cтолкнулся с проблемой:
sensors.ts:
export const sensorsActions = {
doGetSensorsListRequest: createAction<string, 'doGetSensorsListRequest'>(
'doGetSensorsListRequest',
),
doGetSensorsListSuccess: createAction<ISensor[], 'doGetSensorsListSuccess'>(
'doGetSensorsListSuccess',
),
doGetSensorsListFailure: createAction<string, 'doGetSensorsListFailure'>(
'doGetSensorsListFailure',
)
}
sensorsThunks.ts
export function doGetSensorsList(svr_id, acc_pu) {
return dispatch => {
dispatch(doGetSensorsListRequest());
return OnlineGateService.getSensorsList(svr_id, acc_pu)
.then(result => dispatch(doGetSensorsListSuccess(result.data.sensors)))
.catch(result => {
dispatch(
alert({
title: 'Ошибка',
text: 'Не удалось получить список счетчиков',
}),
);
return dispatch(doGetSensorsListFailure(result));
});
};
}
sensorsReduser.ts
type SensorsState = {
inProgress: boolean;
sensorsList: ISensor[];
};
const initialState: SensorsState = {
inProgress: false,
sensorsList: [],
};
export default createReducer(initialState, builder => {
builder.addCase(doGetSensorsListRequest, state => {
startLoading(state);
});
builder.addCase(doGetSensorsListSuccess, (state, action) => {
state.inProgress = false;
state.sensorsList = action.payload;
});
builder.addCase(doGetSensorsListFailure, (state, action) => {
loadingFailure(state, action);
});
}
SensorsList.tsx
class SensorsList extends Component<Props, State> {
...
data = [
{title: 'Активные счетчики', data: this.props.sensors.active},
{title: 'Архивные счетчики', data: this.props.sensors.archived},
];
componentDidMount() {
this.loadData(this.info.id, this.info.account_id);
}
renderRow = rowData => {
...
const sensorInfo = (
<View style={styles.sensorRow}>
<RoundLabel
icon_name={rowData.sensor_type.icon_name}
color={icon_color}
/>
<View style={styles.directionColumn}>
<Text style={styles.textMain}>{rowData.display_name}</Text>
{rowData.custom_name ? (
<Text
style={styles.textThird}
numberOfLines={1}
ellipsizeMode={'tail'}>
{rowData.custom_name}
</Text>
) : null}
</View>
<View style={{flexDirection: 'column', alignItems: 'flex-end'}}>
<Text style={styles.textMain}>{rowData.last_sensor_value}</Text>
<Text style={styles.textThird}>{rowData.last_sensor_date}</Text>
</View>
</View>
);
return (
<TouchableHighlight
...
onPress={() => navigation.push('sensorDetail', {})}>
{sensorInfo}
</TouchableHighlight>
);
};
render() {
return (
<SectionList
sections={this.data}
keyExtractor={(item, index) => item + index}
renderItem={({item}) => this.renderRow(item)}
renderSectionHeader={({section: {title}}) => (
<Text style={styles.textSecond}>{title}</Text>
)}
refreshing={this.props.inProgress}
onRefresh={() => this.loadData(this.info.id, this.info.account_id)}
/>
);
}
loadData = (srvId, accPu) => {
this.props.loadData(srvId, accPu);
};
}
const dataSelector = createSelector(
[(state: AppState) => state.sensors.sensorsList],
state => ({
active: state.filter(item => item.status_name === 'Активен'),
archived: state.filter(item => item.status_name === 'Перемещен в архив'),
}),
);
const connector = connect(
(state: AppState) => {
return {
sensors: dataSelector(state),
inProgress: state.sensors.inProgress,
};
},
{
loadData: doGetSensorsList,
},
);
type ReduxProps = ConnectedProps<typeof connector>;
export default connector(SensorsList);
После того как отработал reducer, стор корректно поменялся, но компонент не перерисовывается и остается пустым.
Ответы (1 шт):
Автор решения: saymurrmeow
→ Ссылка
Проблема была в том что SectionList брал данные из свойства data:
class SensorsList extends Component<Props, State> {
...
data = [
{title: 'Активные счетчики', data: this.props.sensors.active},
{title: 'Архивные счетчики', data: this.props.sensors.archived},
];
...
}
Чтобы всё заработало нормально я
переделал dataSelector:
const dataSelector = createSelector(
[(state: AppState) => state.sensors],
state => ({
sensors: [
{
title: 'Активные счетчики',
data: state.sensorsList.filter(
item => item.status_name === 'Активен',
),
},
{
title: 'Архивные счетчики',
data: state.sensorsList.filter(
item => item.status_name === 'Перемещен в архив',
),
},
],
};
)
);
и переделал SectionList:
<SectionList
sections={this.props.sensors.sensors}
extraData={this.props.sensors}
keyExtractor={(item, index) => item + index}
renderItem={({item}) => this.renderRow(item)}
renderSectionHeader={({section: {title}}) => (
<Text style={styles.textSecond}>{title}</Text>
)}
refreshing={this.props.inProgress}
onRefresh={() => this.loadData(this.info.id, this.info.account_id)}
/>;