Redux - niby działa, ale wyrzuca błąd

0

To moje pierwsze podejście do Reduxa (od razu z Thunkiem, żeby zrobić coś sensownego) i właściwie pierwsze zacięcie. Właściwie uzyskuję przewidywany wynik, niemniej po drodze wyskakuje komunikat o błędzie i nie wiem co z tym zrobić. Przejdźmy do szczegółów.

index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import ConnectedApp from './App';
import * as serviceWorker from './serviceWorker';
import './styles/App.css';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import { reducer } from './reducer';
//import registerServiceWorker from './registerServiceWorker';
const store = createStore(reducer, applyMiddleware(thunk) );

ReactDOM.render(<Provider store={store}><ConnectedApp /></Provider>, document.getElementById('root'));

serviceWorker.unregister();

App.js

import React, {useEffect} from 'react';
import {getData} from './actions';
import {connect} from 'react-redux';
import './styles/App.css';

function App(props) {

  useEffect(() => getData(), []);
  console.log(props);
  return (
    <div className="App">
      
    </div>
  );
}
const mapStateToProps = (state) => {
  return {state};
};
const mapDispatchToProps = getData;
const ConnectedApp = connect(mapStateToProps, mapDispatchToProps)(App);

export default ConnectedApp;

dispatcher (fragment actions.js)


export function getData() {
  console.log('getdata');
  return dispatch => {
    console.log('dispatch');
    // set state to "loading"
    dispatch(getDataRequested());

    fetch("https://api.myjson.com/bins/8qjek")
      .then(response => response.json())
      .then(data => {
        // set state for success
        dispatch(getDataDone(data));
      })
      .catch(error => {
        // set state for error
        dispatch(getDataFailed(error));
      })
  }
}


Powyżej index.js i app.js apki, są jeszcze oczywiście akcje i reducer. A problem jest taki, że choć console.log w app.js pokazuje to czego sie spodziewam - czyli pokazuje, że najpierw jest loading a potem już nie ma loading ale są pobrane trzy rekordy - i to własciwe rekordy - to po drodze wyskakuje błąd:

mapDispatchToProps in connect(App) should return a plain object, instead received undefined. 

i nie mam bladego pojęcia, dlaczego. Kod właściwie jest składanką kilku fragmentow z tutków sieciowych.

1

A może tak?

const mapDispatchToProps = dispatch => ({
  getData: () => dispatch(getData())
})

mapDispatchToProps ma być funkcją przyjmującą dispatch i zwracającą obiekt. U Ciebie mapDispatchToProps jest thunkiem. https://react-redux.js.org/using-react-redux/connect-mapdispatch

0
nobody01 napisał(a):

A może tak?

const mapDispatchToProps = dispatch => ({
  getData: () => dispatch(getData())
})

mapDispatchToProps ma być funkcją przyjmującą dispatch i zwracającą obiekt. U Ciebie mapDispatchToProps jest thunkiem..

Działa jak złoto :) trochę mnie zaskoczyło, że getData stało się częścią store ( w każdym razie jest przekazywane przez props). W niczym to nie przeszkadza, ale czy to normalne? skomplikowany ten Redux.

0

getData jest tak jakby przekazywane to propsów komponentu, który podłączyłeś do Reduxa, abyś mógł łatwiej wywoływać zmiany w stanie, który kontroluje Redux. Jest to raczej powszechne, ale nie obowiązkowe. Jeśli nie przekażesz mapDispatchToProps do connect, do propsów zostanie przekazane domyślnie dispatch i będziesz mógł zrobić props.dispatch(getData()) (jest to pokazane w linku wyżej). Pierwsze podejście ma tę zaletę, że komponent staje się nieświadomy istnienia Reduxa (wszystko, czego potrzeba, jest w propsach).

1

Właściwie to można to jeszcze uprościć: jeśli mapDispatchToProps będzie obiektem, to Redux automatycznie przekaże to, co trzeba na podstawie przyjętych konwencji: const mapDispatchToProps = { getData } Najlepiej przeczytać dokumentację ;)

0

Ale korzystając z okazji: próbowałem połaczyć reduktory przez combineReducers. i własciwie połaczyłem ale skutek jest zaskakujący... poczatkowo zaskakujący, tzn po przeczytaniu trzech postów
https://reactgo.com/how-to-combine-reducers-redux/
https://stackoverflow.com/questions/45803876/not-able-to-combinereducers
https://blog.jakoblind.no/code-your-own-combinereducers/

Chodzi o to, że jak początkowo sam stwierdziłem, a potem wyczytałem, użycie combineReducers daje state o trochę bardziej zawiłej strukturze. Może to ma swoje zalety, ale na pierwszy rzut oka ma i wady ( niech na przykład dwa reducery mają modyfikować ten sam klucz stanu: nie modyfikują tego samego, ale powstają dwa rożne). No i tu jest pies pogrzebany: czy można tak użyć combineReducers, żeby state zachował płaską strukturę? Pewnie, jak napisałem, taka złożona struktura ma sens, ale na moim etapie czym prościej, tym lepiej - z drugiej strony sama idea za combineReducers jest fantastyczna.

0

Jeśli ma być prosto, to może po prostu lepiej wyrzucić tego Reduxa (na którego hype zresztą maleje ostatnio)? Tu jest pokazane, jak można mieć globalny stan przy użyciu Context API i hooków. ;)

0

Cześć ponownie, pochwaliłem dzień przed zachodem słońca - oba powyższe rozwiązania i owszem nie wyrzucają błędu, ale nie dają właściwego (tzn. dają pusty(początkowy)) stan)

1 użytkowników online, w tym zalogowanych: 0, gości: 1