如何在初始渲染时防止 Redux 中 Reducer 的硬编码初始状态

问题描述 投票:0回答:1

我通过 reducer 的初始状态获取类别状态项,但它看起来有点混乱和硬编码的方式来获取 redux 状态,因此,我只想获取我自己创建的虚拟 JSON 数据和使用 json-server 包服务,但是,我无法在 useEffect 钩子内部的渲染之前设置初始状态女巫调度 redux-saga。有没有办法解决这种情况?

您可以在代码块下方了解动作的故事;

减速块;没有我想用空对象更改的初始调度,下面的代码块

export const getCategoryReducer = (
    state = {
        category: [
            {
                id: '1',
                name: 'bread',
                url: 'https://via.placeholder.com/210/00FF00?text=1',
                alt: 'bread',
            },
            {
                id: '2',
                name: 'croissant',
                url: 'https://via.placeholder.com/220/00FF00?text=2',
                alt: 'sdfalksdjflkasjdfk',
            },
            {
                id: '3',
                name: 'birthday-cake',
                url: 'https://via.placeholder.com/230/00FF00?text=3',
                alt: 'sdfalksdjflkasjdfk',
            },
        ],
        loading: false,
        err: '',
    },
    action
) => {
    switch (action.type) {
        case LOAD_CATEGORY:
            return {
                ...state,
                loading: true,
            };
        case GET_CATEGORY_SUCCESS:
            return {
                ...state,
                category: action.category,
                loading: false,
            };
        case GET_CATEGORY_FAIL:
            return {
                ...state,
                err: action.message,
                loading: false,
            };
        default:
            return state;
    }
};

注意:initialState 的项目比上面的代码块多

我通过 Redux-saga 尝试了带有调度操作的 UseEffect Hooks,但它不会在页面呈现之前加载 json-server 面包店类别项目;

useEffect(() => {
        dispatch(getCategoryFetch('Bakery'));
    }, []);

这是生成器函数,当动作通过时触发,然后从我由 json-server 创建的本地服务器获取数据;

import { call, put, takeLatest } from 'redux-saga/effects';

const categoryFetch = async (category) => {
    const res = await fetch(`http://localhost:3500/categories:`);

    if (!res.ok) {
        throw new Error('Something went wrong');
    }

    const data = await res.json();

    return data[`${category}`];
};

function* getCategory(action) {
    try {
        const category = yield call(categoryFetch, action.payload);
        yield put({ type: GET_CATEGORY_SUCCESS, category });
    } catch (err) {
        yield put({ type: GET_CATEGORY_FAIL, message: err.message });
    }
}

export default function* mySagaCategory() {
    yield takeLatest(LOAD_CATEGORY, getCategory);
}

在下面的代码中状态渲染动态类别项目;

import React, { useCallback, useEffect, useMemo } from 'react';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import {
    LazyLoadImage,
    LazyLoadComponent,
} from 'react-lazy-load-image-component';
import './ProductContainer.css';

const ProductConatiner = ({ category, err, loading, clickHandler }) => {
    if (loading) {
        document.querySelector('.progress-item').style.display = 'none';
        return (
            <SkeletonTheme className="container">
                <Skeleton
                    color="grey"
                    highlightColor="#AAA"
                    className="handle skeleton"
                    // duration={2.5}
                    // height="55"
                ></Skeleton>
            </SkeletonTheme>
        );
    }

    if (err.length > 0) {
        document.querySelector('.progress-item').style.display = 'none';
        return (
            <h1
                style={{
                    display: 'flex',
                    justifyContent: 'center',
                    alignItems: 'center',
                    color: 'red',
                }}
            >
                {err + ' reload the page'}
            </h1>
        );
    }

    useEffect(() => {
        document.querySelector('.progress-item').style.display = 'block';
    }, []);

    function quantityHandler() {
        console.log('quantityHandler');
    }

    const Images = useMemo(() => {
        return category.map((el, idx) => {
            return (
                <LazyLoadComponent>
                    <LazyLoadImage
                        delayTime={250}
                        delayMethod="throttle"
                        useIntersectionObserver={true}
                        threshold={500}
                        effect="opacity"
                        key={el.id}
                        src={el.url}
                        alt={el.name}
                    />
                    <input
                        key={idx + 'input'}
                        className="image-input"
                        onChange={quantityHandler}
                        type="number"
                        value="1"
                    ></input>
                    <label>kg</label>
                </LazyLoadComponent>
            );
        });
    }, [category]);

    return (
        <div className="container">
            <button
                onClick={(e) => clickHandler(e.target)}
                className="handle left-handle"
            >
                <div className="text">&#8249;</div>
            </button>
            <div className="slider">{Images}</div>
            {/* <div className="inputs">{quantityItems} </div> */}
            <button
                onClick={(e) => clickHandler(e.target)}
                className="handle right-handle"
            >
                <div className="text">&#8250;</div>
            </button>
        </div>
    );
};

export default ProductConatiner;
```
reactjs redux redux-saga
1个回答
0
投票

这在页面呈现之前不加载是完全正常的,即使你找到一种方法来做到这一点(通过延迟应用程序的启动),它也不能反映当今 React 开发的“现实”。

你的组件在没有它需要的数据的情况下渲染是正常的,然后一个 useEffect 被执行,并且任何时候(可能是 10 毫秒,可能是 10 秒)服务器响应。在您的组件之间负责检测数据不存在并呈现“加载”状态。
由于这种模式对于您所做的几乎所有事情都是现实的,因此在这种情况下,您不会通过“作弊”来学到实质性的东西。从一开始就学习它。

总而言之,您在这里使用的 Redux 风格已经严重过时了。现代 Redux(自 2019 年起)不使用 switch..case reducers 或 ACTION_TYPES。此外,对于大多数用例,不再推荐使用 Redux-saga。由于现代 Redux 仅占代码的 1/4 左右,因此您不仅在编写过时的代码,而且还在编写不必要的代码量。请阅读这篇关于现代 Redux 的文章,然后考虑遵循官方 Redux 教程

PS:你在那里用

document.querySelector
做什么,使用外部元素的 css 样式作为“状态源”是有问题的 - 更新这些外部值永远不会使你的组件重新渲染。这意味着您的组件和那些外部值很容易失去同步。为此使用本地或全局(Redux)状态,但不是任意元素属性。这些与您的应用程序生命周期不同步。

© www.soinside.com 2019 - 2024. All rights reserved.