Реагировать на редуксы обновляет элемент списка, но превращает элемент в массив - PullRequest
0 голосов
/ 18 апреля 2019

Я использую реагирующий редукс с реагирующим родным, у меня есть плоский список фотографий. Когда я нажимаю кнопку «Мне нравится», я хочу обновить только одну фотографию в плоском списке. Следующий код, кажется, работает, и статус фотографии, как, обновляется, но каким-то образом мой канал испортился после обновления. До обновления this.props.feed[index] - это отдельный объект, после обновления this.props.feed[index] становится массивом объектов, что я делаю не так? Я получил идею от: https://stackoverflow.com/a/47651395/10906478

Но также кажется неэффективным циклически перебирать все элементы плоского списка, чтобы найти тот, который соответствует переданному в photoId. Есть ли лучший способ?

Экран:

toggleLike = async(photoId, index) => {
    console.log("before: ", this.props.feed[index]);
    await this.props.toggleLike(photoId);
    console.log("after: ", this.props.feed[index]);
}

...

<FlatList
    data = {this.props.feed}
    keyExtractor = {(_, index) => index.toString()}
    renderItem = {({item, index}) => (
        <View key={index}>
            <TouchableOpacity onPress={()=> this.toggleLike(item.photoId, index)}>
                <Text>Button</Text>
            </TouchableOpacity>
        </View>
    )}
/>

Действие

export const toggleLike = (photoId) => async(dispatch) => {
    dispatch({type: "UPDATE_ITEM", photoId: photoId})
}

Переходник

export default (state = initialState, action) => {
    switch(action.type) {
        case "UPDATE_ITEM":
            return {...state, feed: [state.feed.map((item,_) => {
                if (item.photoId === action.photoId) {
                   return { ...item, liked: !item.liked };
                }
                return { ...item };
            })]};

        // other cases

Ответы [ 2 ]

0 голосов
/ 18 апреля 2019

Чтобы лента была массивом, внимательно посмотрите на свой код.Вы увидите, что обернули значение feed в квадратные скобки и запустите карту в массиве.Так что feed - это массив, а карта - это тоже массив.Вот почему у вас есть массив объектов в каждой точке индекса для state.feed.Обычно я предлагаю вам избавиться от окружающих квадратных скобок и позволить вашей карте создать массив.

Однако это не является основной причиной проблемы, и есть более полное решение.

Если необходимо найти совпадающий идентификатор и обновить «понравившееся» значение без изменения порядка массива, попробуйте использовать findIndex вместо сопоставления в массиве.Найдите индекс, где находится ваш элемент, и обновите только это значение.Возможно, вам придется создать клон массива и внутренних объектов, если он жалуется на непосредственное изменение значения хранилища Redux.

Удачи!

0 голосов
/ 18 апреля 2019

Вы вызываете map внутри массива, который возвращает вложенный массив:

return {...state, feed: /* Here ->*/[state.feed.map((item,_) => {
    if (item.photoId === action.photoId) {
        return { ...item, liked: !item.liked };
    }
    return { ...item };
})]};

Это должно сделать:

return {
  ...state, // Current state
  feed: state.feed.map((item, _) => { // map returns a new array
    if (item.photoId === action.photoId) {
      item.liked = !item.liked;
    }
    return item;
  })
}
...