React + redux - store is not defined (

Всем привет.

Начал изучать react + redux и сразу же столкнулся с проблемами. Никак не могу изменить данные с помощью dispatch.

На данный момент моя задача при заходе на страницу, кинуть ajax запрос, получить данные и отрендерить их. Что у меня есть:

index.js

import React from 'react’
import ReactDOM from 'react-dom’
import App from './containers/App’
import { createStore } from 'redux’
import { Provider } from 'react-redux’
import reducer from ‘./reducers’

const store = createStore(reducer, window.REDUX_DEVTOOLS_EXTENSION && window.REDUX_DEVTOOLS_EXTENSION())

ReactDOM.render(
        <Provider store = {store}>
            <App/>
        </Provider>
        ,
    document.getElementById('panel-body')
);

reducer.js

import { combineReducers } from 'redux'
import todos from './todos'

export default combineReducers({
    todos
})

todos.js

const initialState = {
    users : [
        'Smells like spirit',
        'Enter Sandman'
    ]
};

export default function playlist(state = initialState, action) {
    switch(action.type) {
        case 'USER_LIST_SUCCESS':
            return Object.assign({}, state, { users: action.users });
    }
    return state;
}

App.js

import React from 'react';
import { Component } from 'react';
import CreateComponentNewInnovations from '../components/CreateComponentNewInnovations'
import CreateTableView from '../components/CreateTableView'



export default class App extends Component {
    render() {
        return (
            <div>
                <CreateTableView/>
            </div>
    )}
}

CreateTableView.js

import React from 'react';
import { Component } from 'react'
import { connect } from 'react-redux'
// import store from '../index'

class CreateTableView extends Component {

    componentDidMount() {
        this.ajax()
    }

    ajax(){
        $.ajax({
            dataType : 'json',
            type     :  'post',
            url      : '/system/get',
            success : function (data) {
               //тут я хочу задать данные и в дальнейшем рендерить
                store.dispatch({
                    type: 'USER_LIST_SUCCESS',
                    users: data
                });

            }
        })
    }

    render(){
        return (
            <div className="container">
                <div className="panel-group">
                    <div className="panel panel-default">
                      
                    </div>
                </div>
            </div>
        )
    }
}

const mapStateToProps = function(store) {
    return {
        users: store.todos.users
    };
}

export default connect(mapStateToProps)(CreateTableView)

Выдает ошибку что не может найти store, но я не могу понять почему) Кто знает в чем проблема?

В принципе как я и думал, в каждом компоненте нужно объявлять

import reducer from '…/reducers’
import { createStore } from ‘redux’

const store = createStore(reducer);

т.е CreateTableView.js получается так

import React from ‘react’;
import { Component } from 'react’
import { connect } from 'react-redux’
import reducer from '…/reducers’
import { createStore } from ‘redux’

const mapStateToProps = function(store) {
return {
users: store.todos.users
};
}

const store = createStore(reducer);

class CreateTableView extends Component {

componentDidMount() {
    this.ajax()
}

ajax(){

    $.ajax({
        dataType : 'json',
        type     :  'post',
        url      : '/system/get',
        success : function (data) {

            store.dispatch({
                type: 'USER_LIST_SUCCESS',
                users: data
            });

        }
    })
}

render(){
    return (
        <div className="container">
            <div className="panel-group">
                <div className="panel panel-default">
                   
                </div>
            </div>
        </div>
    )
}

}

export default connect(mapStateToProps)(CreateTableView)

но пока так и не понял, зачем же я основном файле index.js прокидывал переменные Provider-дером, если я должен в каждом компоненте указывать createStore для его дополнения - изменения.

Внутри области видимости функции нет переменной store. Обычно ссылку на redux store передают через props в родительском компоненте.

Передай store по цепочке компонент от самого корневого (это считается хорошей практикой) до того, в котором вызываешь dispatch. И обращайся к store через this.props.store.

N.B обрати внимание на this внутри success коллбека. Он не будет ссылаться на инстанс реакт компонента как тебе надо для корректного обращения к this.props.store

1 лайк

ааа, ну вот все и встало на свои места) Спасибо)

Привет, я думал решить проблему с success объявлением переменной перед ajax и выводом this.props… = этой переменной. Но так не получается, т.к при вызове функции ajax, он все рендерит не подождав ответа и в переменной оказывается = 0.
Подскажи как правильно это делать? Для этого нужны асинхронные эксешы?

т.е сейчас у меня код:

import React from 'react';
import { Component } from 'react'
import { connect } from 'react-redux'

class CreateTableView extends Component {

    componentWillMount() {
        this.ajax()
    }

    ajax(){
        var getData = [];
        $.ajax({
            dataType : 'json',
            type     :  'post',
            url      : '/system/get',
            success : function (data) {
                getData = data;
                console.log('ok2');
                console.log(getData);
                //this.props.onAddInnovationsInTheSystem(getData); // тут его не видно
            }
        })
        console.log('ok3');
        console.log(getData);
        this.props.onAddInnovationsInTheSystem(getData); // тут все хорошо, но getData = []
    }

    render(){
        return (
            <div className="container">
                <div className="panel-group">
                    <div className="panel panel-default">
                       
                    </div>
                </div>
            </div>
        )
    }
}

export default connect(
    state => ({
        data : state
    }),
    dispatch => ({
        onAddInnovationsInTheSystem : (data) => {
            dispatch({ type : 'ADD_DATA' , data : data })
        }
    })
)(CreateTableView)

т.е у меня срабатывает сначала ‘ok3’, а потом ‘ok2’ (

Если я функцию ajax вызову в файле index.js , в основном где все рендериться

import React from 'react'
import ReactDOM from 'react-dom'
import App from './containers/App'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import reducer from './reducers'

const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())

function ajax(){
    $.ajax({
        dataType : 'json',
        type     :  'post',
        url      : '/system/get',
        success : function (data) {
            store.dispatch({
                type: 'ADD_DATA',
                users: data
            });
        }
    })
}

ajax()

ReactDOM.render(
        <Provider store = {store}>
            <App />
        </Provider>
        ,
    document.getElementById('panel-body')
);

Это будет правильно? или костыль?

Структурно второй пример, когда ты в ajax ответе вызываешь action, корректный. Нарратив в котором ты разрабатываешь на реакте и редаксе следующий: есть stor-ы, их передаю через props-ы в компоненты, описываю как компоненты рендерят данные из этих stor-ов, и триггерю экшены сторов из компонент.

Я бы делал ajax запрос в том компоненте, который нуждается в данных из запроса. Структурно это выглядит так:

ajax(){
    var _self = this
    $.ajax({
        dataType : 'json',
        type     :  'post',
        url      : '/system/get',
        success : function (data) {
            _self.props.store.dispatch({
                type: 'data',
                data: data
            })
        }
    })
1 лайк