redux React、重新选择和减少asyncThunk

9njqaruj  于 2023-01-05  发布在  React
关注(0)|答案(2)|浏览(106)

如何对从asyncThunk获得的数据使用自定义groupby函数我想将从API获得的原始数组存储在“redux store”中,然后我想更改数据(通过使用groupby函数)并显示它
例如,我有一个函数,它需要调用API '

export const getAnimals = createAsyncThunk(
    'animals/getAnimals',
    async function(_, {rejectWithValue}) {
        try {
            const response = await fetch('http://127.0.0.1:3001/animals')
            if (!response.ok) {
                throw new Error('Problem');
            }
            const data = await response.json();
            return data;
        } catch (error) {
            return rejectWithValue(error.message)
        }
    }
);

第一个月

"animals": [
     {"animal_type": "dog","name": "Jack", "id":1},
     {"animal_type": "cat","name": "Kitty", "id":2},
     {"animal_type": "bird","name": "Red", "id":3},
     {"animal_type": "dog","name": "Tatoshka", "id":4},
     {"animal_type": "dog","name": "Rasl", "id":5},
     {"animal_type": "bird","name": "blue", "id":6},
     {"animal_type": "cat","name": "murr", "id":7},
     {"animal_type": "snake","name": "Van", "id":8},
     {"animal_type": "cat","name": "kshh", "id":9},
     {"animal_type": "dog","name": "Mailo", "id":10},
     {"animal_type": "cat","name": "barsik", "id":11},
     {"animal_type": "monkey","name": "Ika", "id":12}
]

I have a slice with extraReducer

const animalSlice = createSlice({
    name: 'animals',
    initialState: {
        animals: [],
        loading: null,
        error: null,
    },
    extraReducers: {
        [getAnimals.pending]: (state) => {
            state.loading = true;
            state.error = null;
        },
        [ggetAnimals.fulfilled]: (state, action) => {
            state.loading = false;
            state.animals = action.payload;
  
        },
        [getAnimals.rejected]: setError,
    }
})

'
在一个公司里我会做类似事情

const fitOptions = [];
    {    
        Object.keys(animals).forEach(function(animal_type, index){
            fitOptions.push(
                <Menu.Item key={index}>
                    <Accordion.Title
                        active={activeIndex === index}
                        content={animal_type}
                        index={index}
                        onClick={() => accordionClick(index)}
                    />
                    <Accordion.Content active={activeIndex === index} content={
                        <Form>
                        <Form.Group grouped>
                            {animals[animal_type].map((animal) => 
                                <Form.Checkbox label={animal.name} name='animal_id' value={animal.id} key={animal.id} />
                            )}
                        </Form.Group>
                        </Form>
                    } />
                </Menu.Item>
            );
        })
    }

'
我有一个函数groupBu,我之前在reducer中调用了它,结果保存保存了“已更改”的数据,但是现在我想在redux中保存原始数组,并在reselect中执行groupBy

const groupBy = (xs, key) => {

        return xs.reduce(function(rv, x) {
            (rv[x[key]] = rv[x[key]] || []).push(x);
            return rv;
            }, {});
        
    };

'
但是我有一个错误,因为这个函数在我得到API调用的结果之前就启动了,好像它必须通过Promise对象作为调用的结果,但是我找不到在这个proupBy函数中使用它的方法
我将感激你的帮助
我尝试创建重新选择
'

export const selectAnimaksByFilter = createSelector(
  [selectAllAnimals, selectActiveFilter],
  (allAnimals, activeFilter) => {

   if (!activeFilter) {
           const grouped = groupBy(allAnimals, 'animal_type');
        
            
        return grouped;
    }
    

  }
);

'
然后得到一个const animals = useSelector(selectAnimaksByFilter);的分量

gpnt7bae

gpnt7bae1#

我在渲染之前将groupBy移动到component,并使用.slice()方法进行设置

const animals = useSelector(selectAllAnimals);
const grouped = groupBy(animals.slice(), 'animal_type');

选择存储中定义的所有动物

export const selectAllAnimals = (state) => state.animals.animals;
g6ll5ycj

g6ll5ycj2#

这里使用reselectcreateSelector是可以的,你需要确保你的函数在数据还没有加载的时候不会崩溃。
在您的例子中,这不会是一个问题,因为您的state.animals.animals的初始值是一个空数组[](而不是undefined),但无论如何,为了安全起见,我将使用一个备用空数组值。

export const selectAllAnimals = (state) => state.animals.animals;

export const selectAnimalsByType = createSelector(
  selectAllAnimals,
  (allAnimals = []) => groupBy(allAnimals, 'animal_type')
);

在组件中:

const animalsByType = useSelector(selectAnimalsByType);

下面是从另一个选择器获取分组字段的版本,如果没有设置,则默认为按'animal_type'分组:

export const selectAnimalsByFilter = createSelector(
  [selectAllAnimals, selectActiveFilter],
  (allAnimals = [], activeFilter = 'animal_type') => groupBy(allAnimals, activeFilter)
);

您的减速器中似乎存在排印错误(gget代替get):

[ggetAnimals.fulfilled]: (state, action) => {

相关问题