Machez
@Machez
Бу!

Как в React Reduxe получить Store переданный через Provider?

Осваиваю React Redux. Вот возник вопрос: как в компоненте в React Reduxe получить Store переданный через Provider? Ниже я привожу код приложения. Суть такая, в файле actions-reducers.js в методе constructor класса ActionsReducers я хотел бы вывести в консоль переданное через Provider хранилище Store... И никак не пойму как это сделать. Нагуглил то, что вроде надо использовать connect для связи хранилища и компонента. Подскажите на пальцах как и что нужно в конечном итоге?

Точка входа в приложение index.js
import React from 'react';
import ReactDOM from 'react-dom';

import App from './components/app';

ReactDOM.render( <App />, document.getElementById("app") );


Роутинг routes.js
import React from 'react';
import { combineReducers, createStore } from 'redux';
import { Provider } from 'react-redux';
import { BrowserRouter, Route, Switch, Link } from 'react-router-dom';

import Header from './header';
import Footer from './footer';

import Home from './home';
import About from './about';
import NotFound from './not-found';
import EDElements from './e-d-elements';
import ActionsReducers from './actions-reducers';

import menReducers from './../reducers/men';
import animalsReducers from './../reducers/animals';

let store = createStore( combineReducers( { menReducers, animalsReducers } ) );

// unsubscribe = store.subscribe( () => console.log( store.getState() ) );

export default (props) => (
    <div>
        <Provider store={store}>
            <BrowserRouter>
                <div>
                    <Header/>
                    <div className="content">
                        <div className='pure-g'>
                            <div className="pure-u-1-5">
                                <nav>
                                    <ul>
                                        <li><Link to="/e-d-elements">Включение и выключение элементов</Link></li>
                                        <li><Link to="/actions-reducers">События и редьюсеры</Link></li>
                                    </ul>
                                </nav>
                            </div>
                            <div className="pure-u-4-5">
                                <Switch>
                                    <Route exact path='/' component={ Home } />
                                    <Route path='/about' component={ About } />
                                    <Route path='/e-d-elements' component={ EDElements } />
                                    <Route path='/actions-reducers' component={ ActionsReducers } />
                                    <Route component={ NotFound } />
                                </Switch>
                            </div>
                        </div>
                    </div>
                    <Footer/>
                </div>
            </BrowserRouter>
        </Provider>
    </div>
);


Работа с хранилищем actions-reducers.js
import React from 'react';

import { add as addMan } from './../actions/men';
import { add as addAnimal } from './../actions/animals';

export default class ActionsReducers extends React.Component {

    constructor() {

        super();
        
        console.log( store );

        // store.dispatch(
        //
        //     addMan( [
        //         { name: 'Альберт', family: 'Эйнштейн' },
        //         { name: 'Мария', family: 'Кюри' },
        //         { name: 'Томас', family: 'Эдисон' } ]
        //     )
        //
        // );

        // store.dispatch(
        //
        //     addAnimal( [
        //         { name: 'Лиса' },
        //         { name: 'Медведь', },
        //         { name: 'Волк' } ]
        //     )
        //
        // );

    }

    getMoreAnimals() {

        // store.dispatch(
        //
        //     addAnimal( [
        //         { name: 'Енот' },
        //         { name: 'Лось', },
        //         { name: 'Рысь' } ]
        //     )
        //
        // );

    }

    render() {

        // let currentState = store.getState();

        // { currentState.animalsReducers.animalsApp.map( function( animal ) { return animal.name + ', ' } ) }

        return (
            <div>
                <main>
                    <h1>Действия и редьюсеры</h1>
                    <div>
                        <div className='pure-g'>
                            <div className="pure-u-1-2">
                                <h2>Люди</h2>
                            </div>
                            <div className="pure-u-1-2">
                                <h2>Животные</h2>
                                <button onClick={this.getMoreAnimals}>Еще</button>
                            </div>
                        </div>
                    </div>
                </main>
            </div>
        );
    }

}
  • Вопрос задан
  • 3311 просмотров
Решения вопроса 1
rockon404
@rockon404 Куратор тега React
Frontend Developer
Макс Мачез, вам не надо обращаться к store напрямую в компоненте, если вы используете react-redux.
Вы не должны мапить весь стор, как это делаете в примере в комментарии, мапьте только данные необходимые компоненту:
const mapStateToProps = state => ({
  userData: state.userData,
});


по-хорошему, для получения части объекта состояния, надо использовать selector pattern, отличная его реализация reselect:
import { createSelector } from 'reselect';

export const userDataSeleror = state => state.userData;

export const userSelector = state => createSelector(
  userDataSelector,
  userData => userData.user,
);

export const isUserDataLoadingSelector = state => createSelector(
  userDataSelector,
  userData => userData.isLoading,
);

export const isUserDataErrorSelector = state => createSelector(
  userDataSelector,
  userData => userData.isError,
);


тогда контейнер для компонента будет примерно такой:
import { fetchUserData } from './somePlace';
import Profile from './Profile';
import {
  userSelector,
  isUserDataLoadingSelector,
  isUserDataErrorSelector,
} from './selectors';

const mapStateToProps = state => ({
  user: userSelector(state),
  isLoading: isUserDataLoadingSelector(state),
  isError:  isUserDataErrorSelector(state),
});

const mapDispatchToProps = {
  fetchUserData,
};

export default connect(mapStateToProps, mapDispatchToProps)(Profile);


Компонент внутри вообще ничего не должен знать про redux, он лишь получает набор обязательных свойств и использует, а откуда они приходят ему не важно:
class Profile extends Component {
  componentDidMount() {
    this.props.fetchUserData();
  }
  
  render() {
    const { user, isLoading, isError } = this.props;
    return (
       ...
    );
  }
}


Все, что вы передаете посредством декоратора connect в компонент, доступно в последнем в его свойствах (this.props), аргументы поэтому так и называются mapStateToProps и mapDispatchToProps. Все actionCreators переданные объектом в mapDispatchToProps оборачиваются в dispatch, внутренним вызовом bindActionCreators.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@kristenstewartdadada
Frontend Developer
используй функцию connect из react-redux пакета, в итоге у тебя будет экспорт копонента выглядеть так:
export default connect(mapStateToProps, mapDispatchToProps)(componentl), где mapStateToProps и mapDispatchToProps функции которые мапят, стейт и акшены соответственно и прокидывают их в пропс твоего компонента, вот линк на пакет который тебе нужен: https://github.com/reactjs/react-redux
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы