【问题标题】:Best Way to load model into redux store on route load在路由加载时将模型加载到 redux 存储的最佳方法
【发布时间】:2018-12-19 03:43:56
【问题描述】:

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

但是当路由发生变化时,将 django 模型加载到 redux 存储中的最佳方法是什么?我在思考逻辑应该走向何方时遇到了麻烦。

如果您查看下面的 repo,您​​会发现我在哪里遇到了麻烦。

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

但是我该怎么做呢?我在哪里调用 action 和 reducer 来正确处理状态?

任何指导将不胜感激。

您可以查看完整的项目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
        ]
    }
});

减速器 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
    }
}

【问题讨论】:

  • 我可能会在组件的componentDidMount 中调用一个操作来检索/存储数据。
  • @NorianNyx 我想了这么多。这实际上是我有一个 axios 调用来检索它的地方。但是在哪里以及如何调用操作以从本地以外的地方推送新状态?
  • 您可以在您的 axios 调用的 .then 方法中调用它,例如:this.props.dispatch({ type: 'RETRIEVE_SUCCESS', payload: res.data })(或任何您的调度操作模式)。然后在你的减速器中:case 'RETRIEVE_SUCCESS': (state, action) => ({ ...state, action.payload })
  • @NorianNyx 我想我做到了,但它不断给我错误,它是未定义的。我在我的问题中添加了相关的代码。我做得对吗?
  • 负载是否未定义?

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


【解决方案1】:

让我们换个角度来看这个问题。与其问“当路由改变时我如何调度一个动作”,不如问“什么是真实的真实来源:Redux 还是 URL?”

如果我们选择 redux 作为单一真相来源,那么这意味着我们需要 dispatch 一些 action 会导致一些副作用(可能是 redux-sagaredux-observable 甚至redux-thunk?) 改变了 url:

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

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

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

如果我们走这条路,这听起来像你想要的,你可能需要连接middleware,这是以下签名的函数:

store => next => action => next(action)

根据您使用的路由器,您可以挂钩他们的操作,也可以挂钩window.onpopstate 并检查下一个网址。无论哪种方式,整个中间件功能看起来都像

const middleware = store => {
  return next => action => {
    if (actionWillCauseSpellToBeNeeded(action)) {
       makeAPICall()
         .then(transformAPIToAction)
         .catch(transformError)
         .then(store.dispatch) 
    }
    return next(action)
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-10
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    相关资源
    最近更新 更多