[英]Is it valid to reuse the same React-Redux's useDispatch on multiple components?
[英]How to reuse the same Redux Saga for multiple React components with their own state?
這是一個冗長的解釋。 盡可能簡短:我有兩個組件, Employees
和AddEmployee
它們分別附加到routes /employees
和employees/add
。 Employee
組件中的鏈接將推送employees/add
到BrowserHistory,反之亦然(如果表單成功提交,或者用戶單擊“取消”, AddEmployee
組件也將推送/employees
)。
如果我導航到/employees
,組件工作正常。 如果我單擊導航到/employees/add
, 該組件可以正常工作。 如果我單擊“取消”或提交表單重定向回/employees
...組件中斷。
通過大量的調試我已經確定這是因為AddEmployee
redux狀態持續到Employee
。 我的猜測是因為他們都使用相同的傳奇。 我已經寫了一個get
終極版傳奇處理請求的遠程API。 Employees
顯然使用get
saga來檢索所有用戶,而AddEmployee
使用get
saga來檢索可能的位置以分配用戶。
加載Employees
, apiGet
saga的狀態包含檢索到的員工。 加載AddEmployee
, apiGet
saga的狀態包含檢索到的位置。 然后,當您導航回 Employees
, apiGet
saga的狀態仍包含檢索到的位置,並且不會再次運行以再次加載員工。
我怎么解決這個問題?
我已盡力將下面的代碼壓縮到相關部分。
get
佐賀:
function getApi(endpoint, token) {
return fetch(apiUrl + endpoint, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
}
}).then(handleApiErrors)
.then(response => response.json())
.catch((error) => {throw error})
}
function* apiGetFlow(endpoint) {
let response, token
try {
token = localStorage.getItem('token')
token = JSON.parse(token)
response = yield call(getApi, endpoint, token)
yield put({ type: CLIENT_GET_SUCCESS, response: response })
} catch(error) {
...
}
return response
}
function* apiGetWatcher() {
while(true) {
const { endpoint } = yield take(CLIENT_GET_REQUESTING)
const task = yield fork(apiGetFlow, endpoint)
}
}
export default apiGetWatcher
Employees
組件:
class Employees extends Component {
componentDidMount() {
this.usersGet()
}
usersGet() {
this.props.apiGetRequest('users')
}
render() {
...
}
}
const mapStateToProps = state => {
return {
users: state.apiGet,
}
}
const connected = connect(mapStateToProps, { apiGetRequest })(Employees)
export default connected
AddEmployee
組件:
class AddEmployeeForm extends Component {
componentDidMount() {
this.locationsGet()
}
locationsGet() {
this.props.apiGetRequest('locations')
}
render() {
...
}
}
const mapStateToProps = state => {
return {
locations: state.apiGet,
save: state.apiPost,
}
}
const formed = reduxForm({
form: 'addemployee',
})(AddEmployeeForm)
const connected = connect(mapStateToProps, { apiGetRequest, apiPostRequest })(formed)
export default connected
我懷疑它是因為你的React組件沒有卸載。 看起來這些組件從componentDidMount
生命周期方法中激活了它們的api請求。
假設您從/employees/
開始, Employees
組件安裝並為用戶分派api請求。
導航到/employees/add
, AddEmployeeForm
組件將安裝並調度位置的api請求。
當您按下並且現在返回/employees
, Employees
組件已經安裝 。 因此,它不會再次為“用戶”觸發請求。
您可以通過使用console.log在每個組件中實現componentWillUnmount
方法來驗證這是否是問題。
話雖如此,在我看來,你不應該在期望數據完全不同的組件之間共享state.apiGet
reducer。 不同的數據應該在我們的減速器中保持狀態。
假設您重構了組件,以便在來回時成功分派API請求,並且state.apiGet
更新。 這真的是你想要的嗎? 每次用戶按下前進和后退時,API響應會不同嗎? 此外,api請求和state.apiGet
將會出現滯后,直到請求完成為止。
我會創建一個users
減速器和locations
減速器。 然后創建兩個包含getApi
方法的傳奇並調度它們的特定操作。
例如:
function* getUsers(endpoint) {
let response, token
try {
token = localStorage.getItem('token')
token = JSON.parse(token)
response = yield call(getApi, endpoint, token)
yield put({ type: 'ADD_USERS', response: response })
} catch(error) {
...
}
return response
}
和
function* getLocations(endpoint) {
let response, token
try {
token = localStorage.getItem('token')
token = JSON.parse(token)
response = yield call(getApi, endpoint, token)
yield put({ type: 'ADD_LOCATIONS', response: response })
} catch(error) {
...
}
return response
}
在您的組件中:
const mapStateToProps = state => {
return {
users: state.users,
}
}
const mapStateToProps = state => {
return {
locations: state.locations,
save: state.apiPost,
}
}
官方Redux Docs中有關於如何創建單獨的reducer的詳細信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.