【问题标题】:How do I access store state in React Redux?如何在 React Redux 中访问存储状态?
【发布时间】:2016-11-14 22:24:19
【问题描述】:

我只是在制作一个简单的应用程序来学习与 redux 的异步。我已经让一切正常,现在我只想在网页上显示实际状态。现在,我如何在 render 方法中实际访问 store 的状态?

这是我的代码(所有内容都在一页中,因为我只是在学习):

const initialState = {
        fetching: false,
        fetched: false,
        items: [],
        error: null
    }

const reducer = (state=initialState, action) => {
    switch (action.type) {
        case "REQUEST_PENDING": {
            return {...state, fetching: true};
        }
        case "REQUEST_FULFILLED": {
            return {
                ...state,
                fetching: false,
                fetched: true,
                items: action.payload
            }
        }
        case "REQUEST_REJECTED": {
            return {...state, fetching: false, error: action.payload}   
        }
        default: 
            return state;
    }
};

const middleware = applyMiddleware(promise(), thunk, logger());
const store = createStore(reducer, middleware);

store.dispatch({
    type: "REQUEST",
    payload: fetch('http://localhost:8000/list').then((res)=>res.json())
});

store.dispatch({
    type: "REQUEST",
    payload: fetch('http://localhost:8000/list').then((res)=>res.json())
});

render(
    <Provider store={store}>
        <div>
            { this.props.items.map((item) => <p> {item.title} </p> )}
        </div>
    </Provider>,
    document.getElementById('app')
);

所以,在 state 的 render 方法中,我想从 store 中列出所有的 item.title

谢谢

【问题讨论】:

标签: javascript asynchronous reactjs redux react-redux


【解决方案1】:

您应该创建单独的组件,该组件将监听状态变化并在每次状态变化时更新:

import store from '../reducers/store';

class Items extends Component {
  constructor(props) {
    super(props);

    this.state = {
      items: [],
    };

    store.subscribe(() => {
      // When state will be updated(in our case, when items will be fetched), 
      // we will update local component state and force component to rerender 
      // with new data.

      this.setState({
        items: store.getState().items;
      });
    });
  }

  render() {
    return (
      <div>
        {this.state.items.map((item) => <p> {item.title} </p> )}
      </div>
    );
  }
};

render(<Items />, document.getElementById('app'));

【讨论】:

  • @1ven 我们如何在这里定义store 变量?
  • @BangDao 我们可以假设,我们正在从外部文件导入它。 store 变量 - 它是 redux 存储实例。
  • @BangDao 为了清楚起见,您应该包含 store 导入。
  • ReferenceError 找不到变量:存储
  • import store from '../reducers/store'; 。而store.js 将包含const createStoreWithMiddleware = applyMiddleware(thunkMiddleware,promise)(createStore); export default createStoreWithMiddleware(reducers);
【解决方案2】:

react-redux导入connect,并用它来连接状态为connect(mapStates,mapDispatch)(component)的组件

import React from "react";
import { connect } from "react-redux";


const MyComponent = (props) => {
    return (
      <div>
        <h1>{props.title}</h1>
      </div>
    );
  }
}

最后,您需要将状态映射到道具以使用this.props 访问它们

const mapStateToProps = state => {
  return {
    title: state.title
  };
};
export default connect(mapStateToProps)(MyComponent);

只有您映射的州才能通过props访问

看看这个答案:https://stackoverflow.com/a/36214059/4040563

进一步阅读:https://medium.com/@atomarranger/redux-mapstatetoprops-and-mapdispatchtoprops-shorthand-67d6cd78f132

【讨论】:

  • 注意:这样,如果不调用操作(在mapDispatchToProps 中定义),道具将无法访问。如果您试图在不调度另一个提取周期的情况下获取商店中已有的内容,那么您必须在store 上使用subscribegetState
【解决方案3】:

您需要使用Store.getState() 来获取您商店的当前状态。

有关getState()的更多信息,请观看this短视频。

【讨论】:

  • 所以我只是将this.props.items 更改为store.getState().items 吗?当我这样做时,它没有输出item.title
  • @Parkicism 看起来您没有为组件进行初始渲染。我强烈推荐你观看这门课程:egghead.io/courses/getting-started-with-redux
  • @Parkicism 这不显示项目,因为当应用程序第一次渲染时,还没有收到服务器的响应,您需要订阅商店,每次商店更改时更新组件。
  • 我在index.js 中有let store = createStore(todoApp);,我想访问App.js 中的store - 它的方法是什么?
  • TypeError: undefined is not an object (evalating '_redux.Store.getState')
【解决方案4】:

所有的答案都来自钩前时代。您应该使用 useSelector-hook 从 redux 获取状态。

在您的 redux-reducer 文件中或您可以轻松导入的地方:

import { useSelector } from 'react-redux'

export function useEmployees() {
  return useSelector((state) => state.employees)
}

在您的应用程序代码中:

const { employees } = useEmployees()

有关 redux-hooks 的更多信息:https://react-redux.js.org/api/hooks 以实现此目标。

【讨论】:

  • 这个钩子会监听store的变化吗?每次更改 store 时它会更新局部变量并重新渲染组件吗?
  • @IbrahimFarooq,是的,确实如此。它的功能类似于传递的道具。
  • 为什么我们需要另一个 hook over useSelector()? const employees = useSelector( state =&gt; state.employees)
  • @Yogi,您可以完全使用它而无需额外的钩子。我个人更喜欢将 Redux 特定的 useSelector 保留在 Redux 文件夹下。次要原因是我发现 useEmployees 更具表现力
  • @IlmariKumpula 谢谢你的解释!这是将 useSelector 调用函数保留在 redux 文件夹下的好格式。
【解决方案5】:

您想做的不仅仅是getState。您想对商店的变化做出反应。

如果你没有使用 react-redux,你可以这样做:

function rerender() {
    const state = store.getState();
    render(
        <div>
            { state.items.map((item) => <p> {item.title} </p> )}
        </div>,
        document.getElementById('app')
    );
}

// subscribe to store
store.subscribe(rerender);

// do initial render
rerender();

// dispatch more actions and view will update

但更好的是使用 react-redux。在这种情况下,您使用前面提到的 Provider,然后使用 connect 将您的组件连接到商店。

【讨论】:

  • 该操作专门要求 React-Redux。为什么要为请求以外的东西提供解决方案?
  • ReferenceError 找不到变量:存储
【解决方案6】:

如果你想做一些高性能的调试,你可以订阅状态的每一次变化,然后暂停应用,看看具体发生了什么,如下所示。

store.js
store.subscribe( () => {
  console.log('state\n', store.getState());
  debugger;
});

把它放在你做createStore的文件中。

要将state 对象从控制台复制到剪贴板,请按以下步骤操作:

  1. 右键单击 Chrome 控制台中的对象,然后从上下文菜单中选择存储为全局变量。它将返回类似 temp1 作为变量名。

  2. Chrome 也有一个copy() 方法,所以控制台中的copy(temp1) 应该将该对象复制到剪贴板。

https://stackoverflow.com/a/25140576

https://scottwhittaker.net/chrome-devtools/2016/02/29/chrome-devtools-copy-object.html

您可以像这样在 json 查看器中查看对象:http://jsonviewer.stack.hu/

您可以在这里比较两个 json 对象:http://www.jsondiff.com/

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2020-11-05
  • 2020-10-07
  • 1970-01-01
  • 2020-10-26
  • 2017-12-05
  • 1970-01-01
  • 2020-06-17
  • 2016-04-21
相关资源
最近更新 更多