Jak uzyskać dostęp do stanu sklepu w React Redux?

86

Po prostu tworzę prostą aplikację do nauki asynchronizacji z Redux. Wszystko działa, teraz chcę po prostu wyświetlić aktualny stan na stronie internetowej. W jaki sposób mogę uzyskać dostęp do stanu sklepu w metodzie renderowania?

Oto mój kod (wszystko jest na jednej stronie, bo dopiero się uczę):

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

Tak więc w metodzie renderowania stanu chcę wyświetlić wszystkie item.titleze sklepu.

Dzięki

Parkycyzm
źródło
5
Już prawie jesteś. Musisz utworzyć komponent podłączony do sklepu za pomocą react-reduxbiblioteki. Gorąco polecam dopracowanie rozumienia reduxu dzięki darmowemu kursowi autora: egghead.io/courses/getting-started-with-redux
ctrlplusb
3
Robisz, store.getState()aby faktycznie odczytać stan ze swojego sklepu. redux.js.org/docs/api/Store.html#getState
Kenny Worden
2
Dzięki za tutorial. Nie do końca rozumiem Redux i ten samouczek bardzo mi pomoże.
Parkicism

Odpowiedzi:

64

Powinieneś stworzyć osobny komponent, który będzie nasłuchiwał zmian stanu i aktualizował przy każdej zmianie stanu:

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
źródło
61
@ 1Nawet jak uzyskać storezdefiniowaną tutaj zmienną?
Bang Dao
3
@Banguesday można założyć, że importujemy go z zewnętrznego pliku. storezmienna - jest to instancja sklepu Redux.
nawet
28
@Banguesday storeDla zachowania przejrzystości należy dołączyć import.
Kurai Bankusu
5
ReferenceError Nie można znaleźć zmiennej: store
Pete Alvin
4
import store from '../reducers/store';. i store.jsbędzie zawieraćconst createStoreWithMiddleware = applyMiddleware(thunkMiddleware,promise)(createStore); export default createStoreWithMiddleware(reducers);
AnBisw
44

Importuj connectz react-reduxi użyj go do połączenia komponentu ze stanemconnect(mapStates,mapDispatch)(component)

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


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

Na koniec musisz zmapować stany do właściwości, aby uzyskać do nich dostęp this.props

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

Tylko stany, które mapujesz, będą dostępne za pośrednictwem props

Sprawdź tę odpowiedź: https://stackoverflow.com/a/36214059/4040563

Więcej informacji: https://medium.com/@atomarranger/redux-mapstatetoprops-and-mapdispatchtoprops-shorthand-67d6cd78f132

Zakher Masri
źródło
1
UWAGA: W ten sposób właściwości nie będą dostępne bez wywołania akcji (zdefiniowanej w mapDispatchToProps). Jeśli próbujesz uzyskać to, co jest już w sklepie bez wysyłania kolejnego cyklu pobierania, musisz użyć albo subscribelub getStatena store.
AnBisw
13

Musisz użyć, Store.getState()aby sprawdzić aktualny stan swojego Sklepu.

Aby uzyskać więcej informacji, getState()obejrzyj ten krótki film.

semanser
źródło
Więc po prostu zmieniam się this.props.itemsna store.getState().items? Kiedy to zrobiłem, nie wyświetla pliku item.title.
Parkicism
1
@Parkicism wygląda na to, że nie wykonałeś wstępnego renderowania dla swojego komponentu. Gorąco polecam obejrzenie tego kursu: egghead.io/courses/getting-started-with-redux
semanser
1
@Parkicism to nie wyświetlanie elementów, ponieważ gdy aplikacja jest renderowana po raz pierwszy, odpowiedź z serwera nie została jeszcze odebrana, musisz zapisać się do sklepu, aby aktualizować komponent za każdym razem, gdy sklep zmienia się.
1
Mam let store = createStore(todoApp);w środku index.jsi chcę wejść do storeśrodka App.js- jak to wygląda?
N Sharma
TypeError: undefined nie jest obiektem (ocena '_redux.Store.getState')
Pete Alvin
6

Chcesz zrobić więcej niż tylko getState. Chcesz reagować na zmiany w sklepie.

Jeśli nie używasz React-Redux, możesz to zrobić:

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

Ale lepiej jest użyć React-Redux. W takim przypadku korzystasz z dostawcy, o którym wspomniałeś, ale następnie użyj connect, aby połączyć swój komponent ze sklepem.

Brandon
źródło
6
Operator poprosił specjalnie o React-Redux. Po co oferować rozwiązanie dla czegoś innego niż żądanie?
Kermit_ice_tea
ReferenceError Nie można znaleźć zmiennej: store
Pete Alvin
3

Jeśli chcesz przeprowadzić debugowanie o dużej mocy, możesz zasubskrybować każdą zmianę stanu i wstrzymać aplikację, aby zobaczyć, co się dzieje szczegółowo w następujący sposób.

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

Umieść to w pliku, w którym to robisz createStore.

Aby skopiować stateobiekt z konsoli do schowka, wykonaj następujące kroki:

  1. Kliknij prawym przyciskiem myszy obiekt w konsoli Chrome i wybierz Zapisz jako zmienną globalną z menu kontekstowego. Jako nazwę zmiennej zwróci coś w rodzaju temp1.

  2. Chrome ma również copy()metodę, więc copy(temp1)w konsoli należy skopiować ten obiekt do schowka.

https://stackoverflow.com/a/25140576

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

Możesz wyświetlić obiekt w przeglądarce json, takiej jak ta: http://jsonviewer.stack.hu/

Możesz porównać dwa obiekty json tutaj: http://www.jsondiff.com/

Pozwól mi się nad tym zastanowić
źródło