How do I access store state in React Redux?

2020-05-12 13:26发布

问题:

I am just making a simple app to learn async with redux. I have gotten everything working, now I just want to display the actual state onto the web-page. Now, how do I actually access the store's state in the render method?

Here is my code (everything is in one page because I'm just learning):

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')
);

So, in the render method of the state I want to list out all the item.title from the store.

Thanks

回答1:

You should create separate component, which will be listening to state changes and updating on every state change:

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'));


回答2:

Import connect from react-redux and use it to connect the component with the state connect(mapStates,mapDispatch)(component)

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


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

Finally you need to map the states to the props to access them with this.props

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

Only the states that you map will be accessible via props

Check out this answer: https://stackoverflow.com/a/36214059/4040563

For further reading : https://medium.com/@atomarranger/redux-mapstatetoprops-and-mapdispatchtoprops-shorthand-67d6cd78f132



回答3:

You need to use Store.getState() to get current state of your Store.

For more information about getState() watch this short video.



回答4:

You want to do more than just getState. You want to react to changes in the store.

If you aren't using react-redux, you can do this:

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

But better is to use react-redux. In this case you use the Provider like you mentioned, but then use connect to connect your component to the store.



回答5:

If you want to do some high-powered debugging, you can subscribe to every change of the state and pause the app to see what's going on in detail as follows.

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

Place that in the file where you do createStore.

To copy the state object from the console to the clipboard, follow these steps:

  1. Right-click an object in Chrome's console and select Store as Global Variable from the context menu. It will return something like temp1 as the variable name.

  2. Chrome also has a copy() method, so copy(temp1) in the console should copy that object to your clipboard.

https://stackoverflow.com/a/25140576

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

You can view the object in a json viewer like this one: http://jsonviewer.stack.hu/

You can compare two json objects here: http://www.jsondiff.com/