在路线加载时将模型加载到Redux存储的最佳方法

时间:2018-07-11 07:36:54

标签: reactjs redux django-rest-framework react-router jwt

我有一个React应用程序,它使用React-Router / React-Router-dom进行页面导航,并使用redux存储一些全局状态信息(例如django rest框架的jwt令牌)。该州还存储有关当前查看页面的信息,例如序列化的Django模型。

但是,当路线更改时,将Django模型加载到Redux存储的最佳方法是什么?我无法确定逻辑应该去哪里。

如果您在下面查看回购,您会发现我在哪里难以确定。

在此示例中,当某人导航到/spells/:id时,应将spell django模型加载到redux存储中,以便可以全局访问有关它的信息。

但是我该怎么做呢?我该在哪里调用动作和减速器以正确处理状态?

任何指导将不胜感激。

您可以查看完整的项目here。这里讨论的组件是LayoutSpellView/frontend/src/components/LayoutSpellView)。那就是模型信息的存储,显示等。

编辑:添加相关代码

致电componentDidMount

axios
    .get("http://localhost:3000/api/spells/" + spellId)
    .then(response => {
        let spell = Object.assign({}, spellView.state.spell);

        spell.id =  response.data.id;
        spell.owner =  response.data.owner;
        ...blahblah other fields

        this.setState({
            spell
        });


    })
    .then(response => {
        this.props.dispatch({
            type: 'FETCH_SPELL_SUCCESS',
            payload: this.state.spell,
        });
    })
    .catch(function(error) {
        console.error('[API]\t', error);
    });

LayoutSpellView中(与上面相同)

import {loadSpell} from "../src/reducers";
const mapStateToProps = (state) => ({
    spell: loadSpell(state.spell.id),
});
const mapDispatchToProps = (dispatch) => ({
    getSpell: (state.spell.id) => {
        dispatch(loadSpell(state.spell.id))
    }
});

动作spell.js:

export const FETCH_SPELL = '@@spell/FETCH_SPELL';
export const FETCH_SPELL_SUCCESS = '@@spell/FETCH_SPELL_SUCCESS';
export const FETCH_SPELL_FAILURE = '@@spell/FETCH_SPELL_FAILURE';

export const loadSpell = (spellId) => ({
    [RSAA]: {
        endpoint: '/api/spell/${spellId}',
        method: 'GET',
        types: [
            FETCH_SPELL, FETCH_SPELL_SUCCESS, FETCH_SPELL_FAILURE
        ]
    }
});

Reducers spell.js:

const initialState = {
    spell: {
        id: 0,
        owner: 0,
        Name: 'Name',
        School: 'unknown',
        Subschool: 'unknown',
    }
};
export default (state=initialState, action) => {
    switch(action.type) {
        case spell_action.FETCH_SPELL_SUCCESS:
            return {
                spell: {
                    id: action.payload.spell.id,
                    owner: action.payload.spell.owner,
                    Name: action.payload.spell.Name,
                    School: action.payload.spell.School,
                    Subschool: action.payload.spell.Subschool,
                }
            };
        default:
            return state;
    }
}

export function loadSpell(state) {
    if (state) {
        return state.spell
    }
}

1 个答案:

答案 0 :(得分:0)

让我们以不同的方式看待这个问题。与其问“路由改变时如何调度动作”,不如问“实际的真实来源是什么:Redux或URL?”。

如果我们将redux作为真理的单一来源,那么那意味着我们需要dispatch一些action会造成一些副作用(也许{{1 }}或redux-saga甚至redux-observable?)更改了网址:

redux-thunk

如果我们将URL作为真理的唯一来源,则将流程更改为:

Comp -> dispatch(action) -> store updates -> URL changes

如果我们沿着这条路线走,这听起来像您想要的,那么您可能需要连接URL changes -> dispatch(action) -> store updates ,这是以下签名的功能:

middleware

根据您使用的路由器,您可以挂钩他们的动作,也可以挂钩store => next => action => next(action) 并检查下一个URL。无论哪种方式,整个中间件功能都将类似于

window.onpopstate