如何从同一个组件分派多个动作?
How to dispatch multiple actions from same component?
我想做的是分派 2 个动作 fetchBrand()
和 fetchDistance()
。我有两个不同的 reducer 和不同的 action creator,他们调用不同的 APIs.
但这里的问题是,它根据 useEffect()
中的顺序只给出一个动作的结果。它在 控制台 中显示两次,但结果来自相同的 API.
如果更改顺序,那么它将对其他 API 的结果进行两次控制。这意味着我的 API 通话对双方都成功,但一次只有 1 API 通话。
这可能是一些功能,但我不知道。我该如何解决?
import { Form, Input, Button, Select } from 'antd'
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { fetchDistance } from '../redux/distanceAction'
import { fetchBrand } from '../redux/brandAction'
const { Option } = Select
const layout = {
labelCol: {
span: 8,
},
wrapperCol: {
span: 10,
},
}
const tailLayout = {
wrapperCol: {
offset: 10,
span: 10,
},
}
const UserForm = (props) => {
const distanceList = useSelector((state) => state.distance)
const brandList = useSelector((state) => state.brand)
const dispatchDistance = useDispatch()
const dispatchBrand = useDispatch()
React.useEffect(() => {
dispatchBrand(fetchBrand()) //dispatching action one
dispatchDistance(fetchDistance()) //dispatching action 2
}, [])
const [form] = Form.useForm()
const onFinish = (values) => {
console.log(values)
props.onSubmitForm(values)
form.resetFields()
console.log(brandList.brand)
console.log(distanceList.distance)
// dispatch(fetchBrand);
// dispatch(fetchDistance);
}
return (
<div className="form-layout">
<h1> hello{distanceList.distance + brandList.brand}</h1>
<Form {...layout} form={form} name="user-form" onFinish={onFinish}>
<Form.Item name="name" label="Hotel Name" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item
name="location"
label="Hotel Location"
rules={[{ required: true }]}
>
<Input />
</Form.Item>
<Form.Item name="distance" label="Distance" rules={[{ required: true }]}>
<Select placeholder="Please select Distance" allowClear>
<Option value="0km">0Km</Option>
<Option value="10km">10Km</Option>
<Option value="30">30km</Option>
</Select>
</Form.Item>
<Form.Item name="brand" label="Brands" rules={[{ required: true }]}>
<Select placeholder="Please select Brand" allowClear>
<Option value="flip">Flipkart</Option>
<Option value="amazon">Amazon</Option>
<Option value="paytm">Paytm</Option>
</Select>
</Form.Item>
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
</div>
)
}
export default UserForm
我的第一个观察是您不需要调用 useDispatch()
两次,也不需要具有单独的 dispatch
命名变量。整个应用只有一个 dispatch
函数,因为整个应用只有一个 Redux store。所以,你只需要 const dispatch = useDispatch()
.
其次,实际逻辑看起来不错,应该 可以正常工作,有或没有固定的 dispatch
名称。所以,我不清楚这里的实际问题是什么,我建议仔细检查那些获取函数的实现。
更新
啊,我想我明白了。
fetchBrand
和 fetchDistance
都在 API 调用成功后调度 相同的 操作类型:dispatch(fetchsuccess(someData))
。两个减速器都在监听相同的动作类型。因此,两个 reducer 最终都会保存返回的第一个数据类型,然后用返回的 second 数据类型覆盖它。
“品牌成功”和“距离成功”需要不同的操作类型。
这里要注意的另一件事是,您正在编写的 Redux 代码的风格已经过时,并且需要手动编写比您应该编写的更多的代码。我们的官方 Redux Toolkit 包将简化您拥有的所有这些代码。例如,createAsyncThunk
将为 success/failure 为您要获取的每种数据类型生成那些独特的操作类型。
请阅读我们文档中的 Redux Fundamentals: Modern Redux with Redux Toolkit 教程页面,了解如何正确使用 Redux Toolkit。
按照 , you can use something more modern library like RTK 中的建议减少样板代码。但是如果你想修复你的代码,你需要做的就是创建 unique 动作类型常量。您可以通过 namespacing(例如 brand/FETCH_SUCCESS
等)来实现它们:
动作创作者:
export const fetchrequest = (name) => {
return {
type: name + FETCH_REQUEST,
};
}
...
减速器:
export const name = "brand/";
export const brandReducer = (state = initialState, action) => {
switch (action.type) {
case name + FETCH_SUCCESS:
return {
...state,
loading: false,
brand: action.payload,
error: "",
}
...
}
};
操作:
import { name } from "./brandReducer";
export const fetchBrand = () => {
return function (dispatch) {
dispatch(fetchrequest(name));
axios
.get(URL_HERE)
.then((response) => {
const brand = response;
dispatch(fetchsuccess(name, brand));
})
...
};
};
你也需要为 距离 actions/reducer 做类似的事情。
PS: 你只需要一个 const dispatch = useDispatch()
.
我想做的是分派 2 个动作 fetchBrand()
和 fetchDistance()
。我有两个不同的 reducer 和不同的 action creator,他们调用不同的 APIs.
但这里的问题是,它根据 useEffect()
中的顺序只给出一个动作的结果。它在 控制台 中显示两次,但结果来自相同的 API.
如果更改顺序,那么它将对其他 API 的结果进行两次控制。这意味着我的 API 通话对双方都成功,但一次只有 1 API 通话。
这可能是一些功能,但我不知道。我该如何解决?
import { Form, Input, Button, Select } from 'antd'
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { fetchDistance } from '../redux/distanceAction'
import { fetchBrand } from '../redux/brandAction'
const { Option } = Select
const layout = {
labelCol: {
span: 8,
},
wrapperCol: {
span: 10,
},
}
const tailLayout = {
wrapperCol: {
offset: 10,
span: 10,
},
}
const UserForm = (props) => {
const distanceList = useSelector((state) => state.distance)
const brandList = useSelector((state) => state.brand)
const dispatchDistance = useDispatch()
const dispatchBrand = useDispatch()
React.useEffect(() => {
dispatchBrand(fetchBrand()) //dispatching action one
dispatchDistance(fetchDistance()) //dispatching action 2
}, [])
const [form] = Form.useForm()
const onFinish = (values) => {
console.log(values)
props.onSubmitForm(values)
form.resetFields()
console.log(brandList.brand)
console.log(distanceList.distance)
// dispatch(fetchBrand);
// dispatch(fetchDistance);
}
return (
<div className="form-layout">
<h1> hello{distanceList.distance + brandList.brand}</h1>
<Form {...layout} form={form} name="user-form" onFinish={onFinish}>
<Form.Item name="name" label="Hotel Name" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item
name="location"
label="Hotel Location"
rules={[{ required: true }]}
>
<Input />
</Form.Item>
<Form.Item name="distance" label="Distance" rules={[{ required: true }]}>
<Select placeholder="Please select Distance" allowClear>
<Option value="0km">0Km</Option>
<Option value="10km">10Km</Option>
<Option value="30">30km</Option>
</Select>
</Form.Item>
<Form.Item name="brand" label="Brands" rules={[{ required: true }]}>
<Select placeholder="Please select Brand" allowClear>
<Option value="flip">Flipkart</Option>
<Option value="amazon">Amazon</Option>
<Option value="paytm">Paytm</Option>
</Select>
</Form.Item>
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
</div>
)
}
export default UserForm
我的第一个观察是您不需要调用 useDispatch()
两次,也不需要具有单独的 dispatch
命名变量。整个应用只有一个 dispatch
函数,因为整个应用只有一个 Redux store。所以,你只需要 const dispatch = useDispatch()
.
其次,实际逻辑看起来不错,应该 可以正常工作,有或没有固定的 dispatch
名称。所以,我不清楚这里的实际问题是什么,我建议仔细检查那些获取函数的实现。
更新
啊,我想我明白了。
fetchBrand
和 fetchDistance
都在 API 调用成功后调度 相同的 操作类型:dispatch(fetchsuccess(someData))
。两个减速器都在监听相同的动作类型。因此,两个 reducer 最终都会保存返回的第一个数据类型,然后用返回的 second 数据类型覆盖它。
“品牌成功”和“距离成功”需要不同的操作类型。
这里要注意的另一件事是,您正在编写的 Redux 代码的风格已经过时,并且需要手动编写比您应该编写的更多的代码。我们的官方 Redux Toolkit 包将简化您拥有的所有这些代码。例如,createAsyncThunk
将为 success/failure 为您要获取的每种数据类型生成那些独特的操作类型。
请阅读我们文档中的 Redux Fundamentals: Modern Redux with Redux Toolkit 教程页面,了解如何正确使用 Redux Toolkit。
按照 brand/FETCH_SUCCESS
等)来实现它们:
动作创作者:
export const fetchrequest = (name) => {
return {
type: name + FETCH_REQUEST,
};
}
...
减速器:
export const name = "brand/";
export const brandReducer = (state = initialState, action) => {
switch (action.type) {
case name + FETCH_SUCCESS:
return {
...state,
loading: false,
brand: action.payload,
error: "",
}
...
}
};
操作:
import { name } from "./brandReducer";
export const fetchBrand = () => {
return function (dispatch) {
dispatch(fetchrequest(name));
axios
.get(URL_HERE)
.then((response) => {
const brand = response;
dispatch(fetchsuccess(name, brand));
})
...
};
};
你也需要为 距离 actions/reducer 做类似的事情。
PS: 你只需要一个 const dispatch = useDispatch()
.