Wie greife ich in React Redux auf den Store-Status zu?

83

Ich mache gerade eine einfache App, um Asynchronität mit Redux zu lernen. Ich habe alles zum Laufen gebracht, jetzt möchte ich nur noch den aktuellen Status auf der Webseite anzeigen. Wie greife ich nun in der Rendermethode auf den Status des Geschäfts zu?

Hier ist mein Code (alles ist auf einer Seite, weil ich gerade lerne):

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

Also, in der Render-Methode des Status möchte ich alle item.titleaus dem Speicher auflisten.

Vielen Dank

Parkizismus
quelle
5
Du bist fast am Ziel. Sie müssen mithilfe der react-reduxBibliothek eine mit dem Geschäft verbundene Komponente erstellen . Ich empfehle Ihnen dringend, Ihr Verständnis von Redux mit dem kostenlosen Kurs des Autors zu verbessern
ctrlplusb
3
Sie tun dies store.getState(), um den Status tatsächlich aus Ihrem Geschäft zu lesen. redux.js.org/docs/api/Store.html#getState
Kenny Worden
2
Danke für das Tutorial. Ich verstehe Redux nicht ganz und dieses Tutorial wird mir sehr helfen.
Parkicism

Antworten:

61

Sie sollten eine separate Komponente erstellen, die Statusänderungen abhört und bei jeder Statusänderung aktualisiert:

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
quelle
60
@ 1ven wie bekommen wir hier eine storeVariable definiert?
Bang Dao
3
@ BangDao können wir davon ausgehen, dass wir es aus einer externen Datei importieren. storeVariable - Es handelt sich um eine Redux-Store-Instanz.
1ven
28
@ BangDao Aus Gründen der storeÜbersichtlichkeit sollten Sie den Import einschließen .
Kurai Bankusu
5
ReferenceError Variable kann nicht gefunden werden: store
Pete Alvin
4
import store from '../reducers/store';. und store.jswürde enthaltenconst createStoreWithMiddleware = applyMiddleware(thunkMiddleware,promise)(createStore); export default createStoreWithMiddleware(reducers);
AnBisw
44

Importieren connectvon react-reduxund verwenden Sie es, um die Komponente mit dem Status zu verbindenconnect(mapStates,mapDispatch)(component)

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


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

Schließlich müssen Sie die Zustände den Requisiten zuordnen, um mit ihnen darauf zugreifen zu können this.props

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

Nur die Staaten, die Sie zuordnen, sind über zugänglich props

Überprüfen Sie diese Antwort: https://stackoverflow.com/a/36214059/4040563

Weitere Informationen: https://medium.com/@atomarranger/redux-mapstatetoprops-and-mapdispatchtoprops-shorthand-67d6cd78f132

Zakher Masri
quelle
1
HINWEIS: Auf diese Weise können die Requisiten nicht aufgerufen werden, ohne die Aktion (definiert in mapDispatchToProps) aufzurufen . Wenn Sie versuchen, das zu erhalten, was sich bereits im Geschäft befindet, ohne einen weiteren Abrufzyklus auszulösen, müssen Sie entweder subscribeoder getStateauf dem verwenden store.
AnBisw
13

Sie müssen verwenden Store.getState(), um den aktuellen Status Ihres Shops abzurufen.

Weitere Informationen finden Sie getState()in diesem kurzen Video.

Semanser
quelle
Wechsle ich einfach this.props.itemszu store.getState().items? Wenn ich es getan habe, gibt es das nicht aus item.title.
Parkicism
1
@Parkicism sieht so aus, als hätten Sie für Ihre Komponente kein erstes Rendering durchgeführt. Ich empfehle Ihnen dringend, diesen Kurs anzuschauen: egghead.io/courses/getting-started-with-redux
semanser
1
@Parkicism Hier werden keine Elemente angezeigt, da beim ersten Rendern der App noch keine Antwort vom Server empfangen wird. Sie müssen den Speicher abonnieren und die Komponente bei jeder Änderung des Speichers aktualisieren.
1ven
Ich habe let store = createStore(todoApp);in index.jsund ich möchte auf das storeInnere zugreifen App.js- Wie ist das?
N Sharma
TypeError: undefined ist kein Objekt (Auswertung von '_redux.Store.getState')
Pete Alvin
6

Sie möchten mehr als nur tun getState. Sie möchten auf Änderungen im Geschäft reagieren.

Wenn Sie React-Redux nicht verwenden, können Sie dies tun:

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

Besser ist es jedoch, React-Redux zu verwenden. In diesem Fall verwenden Sie den von Ihnen erwähnten Anbieter, verwenden dann jedoch connect , um Ihre Komponente mit dem Store zu verbinden.

Brandon
quelle
6
Die Operation fragte speziell nach React-Redux. Warum eine Lösung für etwas anderes als die Anfrage bereitstellen?
Kermit_ice_tea
ReferenceError Variable kann nicht gefunden werden: store
Pete Alvin
3

Wenn Sie ein leistungsstarkes Debugging durchführen möchten, können Sie jede Änderung des Status abonnieren und die App anhalten, um zu sehen, was im Detail wie folgt vor sich geht.

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

Platzieren Sie das in der Datei, in der Sie es tun createStore.

stateGehen Sie folgendermaßen vor, um das Objekt von der Konsole in die Zwischenablage zu kopieren :

  1. Klicken Sie mit der rechten Maustaste auf ein Objekt in der Chrome-Konsole und wählen Sie im Kontextmenü die Option Als globale Variable speichern. Es wird so etwas wie temp1 als Variablennamen zurückgegeben.

  2. Chrome hat auch eine copy()Methode, daher copy(temp1)sollte dieses Objekt in der Konsole in Ihre Zwischenablage kopiert werden.

https://stackoverflow.com/a/25140576

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

Sie können das Objekt in einem JSON-Viewer wie diesem anzeigen: http://jsonviewer.stack.hu/

Sie können zwei json-Objekte hier vergleichen: http://www.jsondiff.com/

Lass mich darüber basteln
quelle