簡體   English   中英

如何使用相同的Redux Saga為多個具有自己狀態的React組件?

[英]How to reuse the same Redux Saga for multiple React components with their own state?

這是一個冗長的解釋。 盡可能簡短:我有兩個組件, EmployeesAddEmployee它們分別附加到routes /employeesemployees/add Employee組件中的鏈接將推送employees/add到BrowserHistory,反之亦然(如果表單成功提交,或者用戶單擊“取消”, AddEmployee組件也將推送/employees )。

如果我導航到/employees ,組件工作正常。 如果我單擊導航到/employees/add組件可以正常工作。 如果我單擊“取消”或提交表單重定向回/employees ...組件中斷。

通過大量的調試我已經確定這是因為AddEmployee redux狀態持續到Employee 我的猜測是因為他們都使用相同的傳奇。 我已經寫了一個get終極版傳奇處理請求的遠程API。 Employees顯然使用get saga來檢索所有用戶,而AddEmployee使用get saga來檢索可能的位置以分配用戶。

加載EmployeesapiGet saga的狀態包含檢索到的員工。 加載AddEmployeeapiGet saga的狀態包含檢索到的位置。 然后,當您導航 EmployeesapiGet 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/addAddEmployeeForm組件將安裝並調度位置的api請求。

當您按下並且現在返回/employeesEmployees組件已經安裝 因此,它不會再次為“用戶”觸發請求。

您可以通過使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM