react-reduxRozpoczęcie pracy z React-Redux


Uwagi

React Redux to biblioteka, która zapewnia powiązania React dla Redux.

Składniki reagujące na informacje o sklepie Redux są nazywane „kontenerami”, „inteligentnymi komponentami” lub „komponentem wyższego rzędu” (HOC). Takie komponenty, aby skorzystać z Redux, muszą:

  • Zapisz się do sklepu, aby otrzymywać aktualizacje ze sklepu Redux
  • Wysyłanie akcji

Wykonanie tego ręcznie oznaczałoby użycie store.subscribe i store.dispatch(action) w kontenerach React.

React Redux upraszcza wiązanie między magazynem Redux a kontenerem React za pomocą funkcji connect , która odwzorowuje właściwości stanu Redux i twórców akcji na rekwizyty komponentu.

connect to funkcja, która tworzy komponent wyższego rzędu. Connect akceptuje 3 funkcje ( mapStateToProps , mapDispatchToProps , mergeProps ) i zwraca komponent kontenera, który otacza oryginalny komponent, aby przekształcić go w komponent „połączony”:

import { connect } from 'react-redux';

const Customers = { ... };
const mapStateToProps = (state) => { ... }
const mapDispatchToProps = (dispatch) => { ... }

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

Kompletny przykład znajduje się w sekcji przykładów.

Ponieważ wszystkie komponenty kontenera muszą mieć dostęp do sklepu Redux, zalecanym sposobem jest użycie specjalnego komponentu <Provider> React Redux, który przekazuje ten sklep do wszystkich komponentów potomnych (wewnętrznie za pomocą kontekstu React).

Oficjalna dokumentacja: http://redux.js.org/docs/basics/UsageWithReact.html

Repozytorium GitHub: https://github.com/reactjs/react-redux

Wersje

Wersja Data wydania
5.0.3 23.02.2017
5.0.2 11.01.2017
5.0.1 14.12.2016
5.0.0 14.12.2016
4.4.6 14.11.2016
4.4.5 14.04.2016
4.4.4 13.04.2016
4.4.3 2016-04-12
4.4.0 2016-02-06
4.3.0 2016-02-05
4.2.0 01.02.2016
4.1.0 28.01.2016
4.0.0 2015-10-15
3.0.0 24.09.2015
2.0.0 01.09.2015
1.0.0 24.08.2015
0,5.0 07.08.2015
0.1.0 2015-07-12

Kompletny przykład

Załóżmy, że mamy kontener „CustomerContainer”, który łączy głupi komponent „Customer” ze sklepem Redux.

W index.js:

import { Component }, React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './redux/rootReducer';
import CustomersContainer from './containers/CustomersContainer';

let store = createStore(rootReducer);

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

W CustomerContainer:

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

// Import action creators
import { fetchCustomers } from '../redux/actions';

// Import dumb component
import Customers from '../components/Customers';

// ES6 class declaration
class CustomersContainer extends Component {
  componentWillMount() {
    // Action fetchCustomers mapped to prop fetchCustomers
    this.props.fetchCustomers();
  }

  render() {
    return <Customers customers={this.props.customers} />;
  }
}

function mapStateToProps(state) {
  return {
    customers: state.customers
  };
}

// Here we use the shorthand notation for mapDispatchToProps
// it can be used when the props and action creators have the same name 
const CustomersContainer = connect(mapStateToProps, { fetchCustomers })(CustomersContainer);

export default CustomersContainer;
 

Hello World za pomocą React Redux

Podręcznik ten zakłada zainstalowano już react , redux , react-router i react-redux i skonfigurowano react , redux i react-router ., Jeśli nie, proszę to zrobić.

Uwaga: Chociaż react-router nie jest zależny od react-redux , jest bardzo prawdopodobne, że użyjemy go w naszej aplikacji Reagowania do routingu, a to sprawia, że bardzo łatwo jest nam użyć Reaktywnego Reduktu.


app.js : app.js

'use strict';

import React from 'react';
import { render } from 'react-dom';
import { Router, Route, Link, browserHistory, IndexRoute } from 'react-router';
import { Provider } from 'react-redux';
import store from './stores';

render(
  (
    <Provider store={ store }>
      <Router history={ browserHistory }>
        {/* all the routes here */}
      </Router>
    </Provider>
  ),
  document.getElementById('app')
);
 

Ten plik będzie miał dla większości z was sens. Chcemy tutaj ./stores sklep z ./stores i przekazać go na wszystkie trasy za pomocą Provider komponentów wyższych zamówień dostarczanego przez react-redux .

Dzięki temu sklep jest dostępny w całej naszej aplikacji.


Rozważmy teraz ten scenariusz . Mamy komponent UserComponent który pobiera dane z reduktora user i ma przycisk, który po kliknięciu aktualizuje dane w sklepie.

Struktura aplikacji

Nasz rootReducer ma reduktor user

const rootReducer = combineReducers({
    user: userReducer,
})
export default rootReducer;
 

Nasz userReducer wygląda następująco

const default_state = {
  users: [],
  current_user: {
    name: 'John Doe',
    email: 'john.doe@gmail.com',
    gender: 'Male'
  },
  etc: {}
};

function userReducer( state=default_state, action ) {

  if ( action.type === "UPDATE_CURRENT_USER_DATA" ) {
    return Object.assign( {}, state, { current_user: Object.assign( {}, state.current_user, { [action.payload.field]: action.payload.value } ) } );
  }
  else {
    return state;
  }

}

export default userReducer;
 

Nasz plik actions wygląda mniej więcej tak

export function updateCurrentUserData( data ) {
  return {
    type: "UPDATE_CURRENT_USER_DATA",
    payload: data
  }
}
 

Wreszcie, pozwala pracować nad naszym komponentem

UserComponent.js : UserComponent.js

'use strict';

import React from 'react';
import { connect } from 'react-redux';
import * as Action from './actions';

let UserComponent = (props) => {

  let changeUserDetails = (field, value) => {
    // do nothing
  }

  return(
    <div>
      <h1>Hello { props.current_user.name }</h1>
      <p>Your email address is { props.current_user.email }</p>
      <div style={{ marginTop: 30 }}>
        <button onClick={ () => { changeUserDetails('name', 'Jame Smith') } }>Change Name</button>
        <button onClick={ () => { changeUserDetails('email', 'jane@gmail.com') } }>Change Email Address</button>
      </div>
    </div>
  )

}

export default UserComponent;
 

Oczywiście to nie zadziała , ponieważ nie podłączyliśmy go jeszcze do sklepu.

Jeśli zastanawiasz się, jest to bezpaństwowy komponent funkcjonalny , ponieważ używamy redux i tak naprawdę nie potrzebujemy wewnętrznego stanu naszego komponentu, jest to właściwy czas, aby go użyć.

Metoda connect zapewniona przez react-redux przyjmuje trzy parametry

mapStateToProps , mapDispatchToProps i sam komponent .

connect( mapStateToProps, mapDispatchToProps )(Component)


Dodajmy połączenie do naszego komponentu UserComponent wraz z mapStateToProps i mapDispatchToProps

I niech aktualizuje również nasze changeUserDetails funkcjonować, więc po nazwie, zostanie on dispatch takie action naszych reducers , oraz na podstawie rodzaju działań nasz reduktor rozpocznie się i wprowadzić zmiany do sklepu, a raz w sklepie zaktualizowanej react-redux ponownie -render nasz komponent z nowymi danymi.

Brzmi skomplikowanie? To naprawdę nie jest.

Będzie wyglądał nasz UserComponent.js

'use strict';

import React from 'react';
import { connect } from 'react-redux';
import * as Action from './actions';

const mapStateToProps = ( state, ownProps ) => {
  return {
    current_user: state.user.current_user,
  }
}

const mapDispatchToProps = ( dispatch, ownProps ) => {
  return {
    updateCurrentUserData: (payload) => dispatch( Action.updateCurrentUserData(payload) ),
  }
}


let UserComponent = (props) => {

  let changeUserDetails = (field, value) => {
    props.updateCurrentUserData({ field: field, value: value });
  }

  return(
    <div>
      <h1>Hello { props.current_user.name }</h1>
      <p>Your email address is { props.current_user.email }</p>
      <div style={{ marginTop: 30 }}>
        <button onClick={ () => { changeUserDetails('name', 'Jame Smith') } }>Change Name</button>
        <button onClick={ () => { changeUserDetails('email', 'jane@gmail.com') } }>Change Email Address</button>
      </div>
    </div>
  )

}

const ConnectedUserComponent = connect(
  mapStateToProps,
  mapDispatchToProps
)(UserComponent)

export default ConnectedUserComponent;
 

To, co tutaj zrobiliśmy, zostało dodane

  • mapStateToProps : Pozwala nam to pobrać dane ze sklepu, a gdy te dane się zmienią, nasz komponent zostanie ponownie renderowany z nowymi danymi.

    Nasz komponent zostanie zrenderowany tylko wtedy, gdy dane, które nasz komponent żąda zmian w sklepie, a nie, gdy inne dane zmienią się w sklepie.

  • mapDispatchToProps : Pozwala nam to na dispatch actions do wszystkich reduktorów z naszego komponentu .. (może to być dowolny komponent), a na podstawie type akcji nasz UserReducer uruchomi i zwróci nowy stan ze zaktualizowanymi danymi.

  • ConnectedUserComponent : Na koniec połączyliśmy nasz komponent ze sklepem za pomocą metody connect , przekazując wszystkie parametry i exported podłączony komponent.

  • Zaktualizowaliśmy również naszą funkcję changeUserDetails, aby wywoływać method na rekwizytach, a także przekazywać dane., A props z kolei wywołują method wywołaliśmy do wszystkich reduktorów.


UWAGA:

  • Jeśli nie zwrócimy nowego stanu z reduktora, react-redux nie react-redux naszego komponentu.

Instalacja lub konfiguracja

Korzystanie redux bezpośrednio react może wydawać się trochę trudne, jak dla każdego component , który chcesz zaktualizować, gdy zmiany w sklepach, trzeba subskrybować tego składnika do redux store

React Redux dba o to wszystko i sprawia, że bardzo łatwo jest pisać komponenty, które mogą zażądać potrzebnych danych ze redux store i otrzymywać powiadomienia Tylko w przypadku zmiany tych danych., To pozwala nam pisać naprawdę skuteczne komponenty.

Aby zainstalować react-redux , wystarczy uruchomić tę komendę npm

npm install --save react-redux
 

I jesteś skończony.


Uwaga: React Redux jest zależny od

  • React (wersja 0.14 lub nowsza) i
  • Redux