I have project with TS+REACT+REDUX TOOLKIT and i fetch some data to my items array. Then using redux toolkit i give to filterMenu (alphabet and birthday filter) and filterSearch (input search) data to filter state in my Main component. And if the filtered array is empty i want to render component SearchFail .
But, when i reload page i got a SearchFail component in a second and then laod my data. I have a slice of users which include isLoading, error and items in state, and initial state of items is empty array, and when i reload page i got my array length 0. So how can i prevent this component loading in this case?
Main.tsx component:
const Main:React.FC = () => {
const {items, isLoading, error} = useAppSelector(state => state.user)
const {filterSearch, filterMenu, filter} = useAppSelector(state => state.filter)
const dispatch = useAppDispatch()
const filterItems = filterMenu === 'alphabet' ? items.slice().sort((a,b) => a.firstName.localeCompare(b.firstName)).filter(item => {
if (filterSearch === '') {
return item
} else {
return item.firstName.toLowerCase().includes(filterSearch.toLowerCase()) ||
item.lastName.toLowerCase().includes(filterSearch.toLowerCase()) ||
item.userTag.toLowerCase().includes(filterSearch.toLowerCase())
}
}) : (
items.slice().sort((a,b) => a.birthday.localeCompare(b.firstName)).filter(item => {
if (filterSearch === '') {
return item
} else {
return item.firstName.toLowerCase().includes(filterSearch.toLowerCase()) ||
item.lastName.toLowerCase().includes(filterSearch.toLowerCase()) ||
item.userTag.toLowerCase().includes(filterSearch.toLowerCase())
}
})
)
useEffect(() => {
dispatch(getUsers(filter))
const timer = setInterval(() => {
dispatch(getUsers(filter))
}, 50000)
return () => clearInterval(timer)
}, [filter])
return (
<main className='main'>
{error && <ErrorPage/>}
{isLoading ? <SkeletonItem count={6}/> :
(filterItems.length === 0) ? <SearchFail/> :
<div className="main__wrapper">
{
filterItems.map(item => (
<MainItem data={item} key={item.id}/>
))
}
</div>
}
</main>
);
};
user-slice.ts:
import {createAsyncThunk, createSlice} from "@reduxjs/toolkit";
import {IItmes, IUser} from "./user-types";
import axios from "axios";
const initialState: IItmes = {
items: [],
isLoading: false,
error: ''
}
export const getUsers = createAsyncThunk<IUser[], string, {rejectValue: string}>(
'user/getUsers',
async (filterName, {rejectWithValue}) => {
try {
const res = await axios.get(`https://stoplight.io/mocks/kode-frontend-team/koder-stoplight/86566464/users?__example=${filterName}`)
return res.data.items
} catch (e) {
return rejectWithValue('critical-error')
}
}
)
export const userSlice = createSlice({
name: 'user',
initialState,
reducers: {},
extraReducers: builder =>
builder
.addCase(getUsers.pending, state => {
state.isLoading = true
state.error = ''
})
.addCase(getUsers.fulfilled, (state, action) => {
state.items = action.payload
state.isLoading = false
localStorage.setItem('items', JSON.stringify(action.payload))
})
.addCase(getUsers.rejected, (state, action) => {
state.isLoading = false
if (action.payload) {
state.error = action.payload
}
})
})
export const userReducer = userSlice.reducer
types for user-slice (user-types.ts):
export interface IItmes {
items: IUser[],
isLoading: boolean,
error: string,
}
export interface IUser {
id: string,
avatarUrl: string,
firstName: string,
lastName: string,
userTag: string,
department: string,
position: string,
birthday: string,
phone: string
}
Thanks for help!
Setting isLoading
state to true
initially would solve the issue.