@morbiuslevakov

Как показать preloader до загрузки страницы?

Я получаю цены и балансы через API, но при первой загрузке react выдает ошибку, поскольку localStorage не содержит этих объектов. Подскажите пожалуйста, как дождаться загрузки данных из API и показать preloader, пока данные не загрузятся. Буду благодарен за любой совет/ответ.
Вот мой код:
Wallet:
class Wallet extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            // state elements
        }
    }
    
    render() {
        const user = JSON.parse(localStorage.getItem("user"));

        if (!user) {
            return <Navigate to="/login" />;
        }

        const { dispatch, history } = this.props;
        
        PriceService.setPrices(this.state.fiat).then(
            response => {
                localStorage.setItem("crypto", JSON.stringify(response.data))
            }, error => {
                if (error.response.status === 403) {
                    EventBus.dispatch("logout");
                    if (!user) {
                        history.push("/register");
                        window.location.reload();
                    }
                }
            }
        );
        PriceService.setBalances(user?.address).then(
            response => {
                localStorage.setItem("balance", JSON.stringify(response.data))
            }, error => {
                if (error.response.status === 403) {
                    EventBus.dispatch("logout");
                    if (!user) {
                        history.push("/register");
                        window.location.reload();
                    }
                }
            }
        );
        
        return (
            <Suspense fallback={<Preloader/>}>
                <div className="content-container">
                    <TableContainer className="table-container">
                        <Table aria-label="simple table">
                            <TableHead>
                                <TableRow>
                                    <TableCell align="left">Name</TableCell>
                                    <TableCell align="left">Price</TableCell>
                                    <TableCell align="left">Amount</TableCell>
                                </TableRow>
                            </TableHead>
                            <TableBody>
                                {
                                    Array.from(Object.entries(JSON.parse(localStorage.getItem("crypto")).assets)).map((value) => {
                                        return (
                                            <TableRow key={value[0]} sx={{'&:last-child td, &:last-child th': {border: 0}}}>
                                                <TableCell align="left">{value[0]}</TableCell>
                                                <TableCell align="left">{value[1].price.toFixed(2)}</TableCell>
                                                <TableCell align="left">
                                                    {
                                                        new Map(Object.entries(JSON.parse(localStorage.getItem("balance")).balance)).get(value[0]).balance
                                                    }
                                                </TableCell>
                                            </TableRow>
                                        )
                                    })
                                }
                            </TableBody>
                        </Table>
                    </TableContainer>
                </div>
            </Suspense>
        );
        
    }
}

function mapStateToProps(state) {
    const { isLoggedIn } = state.auth;
    const { message } = state.message;
    return {
        isLoggedIn,
        message
    };
}
export default connect(mapStateToProps)(Wallet);


PriceService:
class PriceService {
    setPrices = (currency) => {
        return api.get("/price/crypto/" + currency);
    }
    setBalances = (address) => {
        return api.get("/asset/get-assets?address=" + address);
    }
}

const priceService = new PriceService();
export default priceService;


api:
import axios from "axios";
import TokenService from "./token.service";

const instance = axios.create({
    baseURL: "http://localhost:8080/api",
    headers: {
        "Content-Type": "application/json",
    },
});

instance.interceptors.request.use(
    (config) => {
        const token = TokenService.getLocalAccessToken();
        if (token) {
            config.headers["Authorization"] = 'Bearer ' + token;
        }
        return config;
    },
    (error) => {
        return Promise.reject(error);
    }
);

instance.interceptors.response.use(
    (res) => {
        return res;
    },
    async (err) => {
        const originalConfig = err.config;

        if (originalConfig.url !== "/auth/signin" && err.response) {
            // Access Token was expired
            if (err.response.status === 401 && !originalConfig._retry) {
                originalConfig._retry = true;

                try {
                    const rs = await instance.post("/auth/refresh-token", {
                        refreshToken: TokenService.getLocalRefreshToken(),
                    });

                    const { accessToken } = rs.data;
                    TokenService.updateLocalAccessToken(accessToken);

                    return instance(originalConfig);
                } catch (_error) {
                    return Promise.reject(_error);
                }
            }
        }

        return Promise.reject(err);
    }
);

export default instance;
  • Вопрос задан
  • 126 просмотров
Пригласить эксперта
Ответы на вопрос 1
@chemdev
Данная проблема решается состояниями isLoading, isError, isSuccess (последнее в принципе вычисляемое). Есть как ряд библиотек, которые это все поставляют (RTK Query, например), но и можно самому это все дописать к axios, но с большой вероятностью придется писать много повторяющегося кода. Это можно поправить кастомным хуком который даст все состояния за один вызов.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы