我通过 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">‹</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">›</div>
</button>
</div>
);
};
export default ProductConatiner;
```
这在页面呈现之前不加载是完全正常的,即使你找到一种方法来做到这一点(通过延迟应用程序的启动),它也不能反映当今 React 开发的“现实”。
你的组件在没有它需要的数据的情况下渲染是正常的,然后一个 useEffect 被执行,并且任何时候(可能是 10 毫秒,可能是 10 秒)服务器响应。在您的组件之间负责检测数据不存在并呈现“加载”状态。
由于这种模式对于您所做的几乎所有事情都是现实的,因此在这种情况下,您不会通过“作弊”来学到实质性的东西。从一开始就学习它。
总而言之,您在这里使用的 Redux 风格已经严重过时了。现代 Redux(自 2019 年起)不使用 switch..case reducers 或 ACTION_TYPES。此外,对于大多数用例,不再推荐使用 Redux-saga。由于现代 Redux 仅占代码的 1/4 左右,因此您不仅在编写过时的代码,而且还在编写不必要的代码量。请阅读这篇关于现代 Redux 的文章,然后考虑遵循官方 Redux 教程。
PS:你在那里用
document.querySelector
做什么,使用外部元素的 css 样式作为“状态源”是有问题的 - 更新这些外部值永远不会使你的组件重新渲染。这意味着您的组件和那些外部值很容易失去同步。为此使用本地或全局(Redux)状态,但不是任意元素属性。这些与您的应用程序生命周期不同步。