Good day! I understand react-redux and use react-thunk components for queries. I can not not how to set the initial state in the reducer from the server (API). I will provide my code, for a better understanding of what is at stake.

index.js

import React from 'react'; import ReactDOM from 'react-dom'; import { createStore, applyMiddleware } from 'redux'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; import axios from 'axios'; import reducers from './reducers/'; import registerServiceWorker from './registerServiceWorker'; import App from './App'; var store = createStore(reducers, applyMiddleware(thunk)); store.dispatch((dispatch) => { axios('http://localhost:3001/api/collections') .then(colections => dispatch({type: 'SET_STATE_COLLECTION', data: colections.data})) }); store.dispatch((dispatch) => { axios('http://localhost:3001/api/books') .then(books => dispatch({type: 'SET_STATE_BOOKS', data: books.data})) }); export default store ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ); registerServiceWorker(); 

App.js

First, in App.js {console.log (this.props)} = {{data: {books: [], collections: []}}, the store data is empty. Then action.type = 'SET_STATE_COLLECTION' for the collection and action.type = 'SET_STATE_BOOKS' for the books filling the store. I also need the data to be initially in the store state, and they are empty and come along with the option shots. I can not understand how to do this, how to put the original state.

 import React, { Component } from 'react'; import { connect } from 'react-redux'; class App extends Component { render() { return <div> { console.log(this.props) } </div> } } export default connect((state) => ({data: state}), (dispatch) => ({}))(App) 

Files ./reducers/

index.js

 import { combineReducers } from 'redux'; import collections from './collections'; import books from './books'; export default combineReducers({ books, collections }) 

collection.js

Here, the state can be set by declaring the collection = [...] variable and writing data to it, and then written to the function as the collectionsReducer ( state = collection ) parameter, but I need to get them from the server initially, and not to declare it.

 export default function collectionsReducer(state, action) { // reducer console.log(action); if (state === undefined) { return state = [] } if (action.type === 'SET_STATE_COLLECTION') { return [...state, action.data] } return state; } 

books.js

 export default function booksReducer(state, action) { // console.log(action); if (state === undefined) { return state = [] }; if (action.type === 'SET_STATE_BOOKS') { return [...state, action.data] } return state } 

Help please who knows how to do this.

    1 answer 1

    First of all, it would be better to transfer api requests to the App component, and connect it to the store

     class App extends React.Component { componentWillMount() { this.props.loadBooks(); this.props.loadCollections(); } ... } 

    Here this.props.loadBooks, this.props.loadCollections are actions that load data. componentWillMount called once when the component is initialized, you can add a flag that says the boot process

    book.reducer

     const initialState = { items: [], isLoading: true, } 

    In the reducer itself already fill the data

     export default function booksReducer(state = initialState, action) { switch(action.type) { case 'SET_STATE_BOOKS': { return { ...state, items: action.payload, isLoading: false, } } default: return state; } } 

    At the expense of the initial filling of data in the store, why is this? You can check whether there is data in the App or not and display a loader or something else.

    But if absolutely a perversion (I'm not sure that it works, you need to check)

     store.dispatch((dispatch) => { Promise.all([ axios('http://localhost:3001/api/books'), axios('http://localhost:3001/api/collections') ]).then((books, collections) => { dispatch({type: 'SET_STATE_BOOKS', data: books}); dispatch({type: 'SET_STATE_COLLECTION', data: colections}); // если не будет работать, то возвращайте Promise.resolve // return Promise.resolve(); }).then(() => { ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ); }) }); 
    • Initially, fill the data in the stack in order to render a collection or books to the page in render (), but this does not work out. data is empty. And you mean to check in the render-e on loader-y, on the content of the data? - Nick
    • and if you need ssr? then such a scheme is not a ride ... - xFloooo
    • @xFloooo Do not roll, render renders an error on the first pass, because No data. - Nick
    • @Nick and you need ssr? - xFloooo
    • xFloooo Is this something related to the server? Most likely no. - Nick