reactjs - 状态改变后 React-Redux 重新渲染
问题描述
我正在尝试理解 React+Redux。所以,现在我正在尝试从 API 获取数据,并面临一个流行的问题:当我更改 Redux 状态时,它不会刷新我的容器组件。
我在这里阅读了几个问题,最常见的问题是变异状态和不正确的connect
使用。我检查了我的代码,一切看起来都很好。我想,这个问题出在 Reqct hookuseState
中,我在其中调用了我的动作生成器。
代码:
动作生成器
export const requestAccounts = () => ({
type: 'REQUEST_ACCOUNTS'
});
export const receivedAccounts = (data) => ({
type: 'RECEIVED_ACCOUNTS',
data
});
export const requestAccountsError = (errText) => ({
type: 'RECEIVED_ACCOUNTS_ERROR',
errText
});
export function getAccounts(clientRef = 1) {
return async function (dispatch) {
async function fetchData() {
let res;
try {
res = await fetch("https://wstest.grant.ua/stubs/accnts.json", { //добавить парамтер "номер клиента"
method: 'GET' // *GET, POST, PUT, DELETE, etc.
});
if (res.ok) {
let resJson = await res.json();
dispatch(receivedAccounts(resJson.acn_list));
}
else {
dispatch(requestAccountsError('Error during accounts request! Status '+res.status));
}
}
catch (err) {
dispatch(requestAccountsError(err.message));
};
}
dispatch(requestAccounts());
await fetchData();
/*I supposed that my problem depends on async loading,
so I tried to comment all above code and uncomment row below - also,
React did not re-render my component...*/
//dispatch(requestAccountsError("ERROR_MESSAGEEEE"));
}
}
减速器
const initialState = {
isFetching : false,
isError : false,
errorText : "",
accounts : []
}
export function acnList(state = initialState, action) {
switch (action.type) {
case "RECEIVED_ACCOUNTS":
return Object.assign({}, state, {
isFetching: false,
isError: false,
errorText: "",
accounts: action.acnList
})
/*I tried to write return { errorText: "123" } - also no re-render.. So, problem is not in
mutating previous state*/
case "RECEIVED_ACCOUNTS_ERROR":
return Object.assign({}, state, {
isFetching: false,
isError: true,
errorText: "ERRTEXTTTT",
accounts: []
})
case "REQUEST_ACCOUNTS":
return Object.assign({}, state, {
isFetching: true,
isError: false,
errorText: "",
accounts: []
})
default:
return state
}
}
容器组件
import { connect } from 'react-redux'
import AcnListComponent from '../../MainMenuComponents/AcnListComponent'
import {getAccounts} from '../actions/actions'
const mapStateToProps = (state, ownProps) => {
return {
acnList: state.acnList.accounts,
isError: state.acnList.isError,
isFetching: state.acnList.isFetching,
errorText : state.acnList.errorText
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
return {
getAccounts: () => {
dispatch(getAccounts())
}
}
}
const AcnListContainer = connect(
mapStateToProps,
mapDispatchToProps
)(AcnListComponent)
export default AcnListContainer
最后,我的部分 React 组件代码。
//imports
function AcnListComponent(props) {
/*here I can see that props are changed sucessfully (according to state). But no re-render!*/
console.log(props);
const {t} = props;
const [isLoading, setIsLoading] = useState(props.isFetching);
const [accounts, setAccounts] = useState(props.acnList);
const [emptyMessage, setEmptyMessage] = useState(props.errorText);
const [isError, setIsError] = useState(props.isError);
useEffect(() => {
if ((accounts.length === 0) && !isError) {
props.getAccounts();
}
}, []); //I need to call this effect only once, when component renders
//renders
看起来真的很奇怪,就像魔术一样)
也许,我做错了什么useEffect
,而不是 Redux?我需要在我的组件呈现时发出此请求,并使用接收到的数据重新呈现它。
解决方案
只是改变const [accounts, setAccounts] = useState(props.acnList);
到const accounts = props.acnList;
在此博客文章中了解更多信息。
您需要对所有更改的道具进行此操作。
编辑
长话短说:
这是将道具复制到状态中的常见错误。
因为道具会随着时间而改变,你需要更新状态以反映道具的变化(如此多的不必要的重新渲染)。最好是直接使用道具。
推荐阅读
- json - 将超类 json 反序列化为子类对象
- css - 为什么在 CSS 样式中按钮和链接的样式相同但类型呈现不同?
- jmeter - 使用 jmeter 对 100 个新用户同时订购产品进行自动化负载测试
- vue.js - IE11 SCRIPT1002 语法错误与 main.js babel 和 webpack 中的 =>
- sql-server - 如果求和值全部为 null,如何使 SQL Server SUM 返回 null
- r - ggplot() 没有预期的数字
- python-3.x - 是否可以从 PySpark Dataframe 轻松创建 Kudu 表?
- java - 如何在 Java 中运行具有策略权限的小程序以读取 MAC 地址
- javascript - 完整日历,当前月份有效
- google-tag-manager - 产品视图数据层 - 为什么它有一个列表视图?