I have heard a lot about redux but never had time to put my hands on it., so i guess the time is come - lets write something about redux.
So, what is redux?
To put the long terms short - it is a way to organize logic which changes the state (application data) of single page application. So if you asking yourself: is redux about to make me write less code? - Well, the answer is no, this is not the point. The point is - to make clear for developer who and why changed the state of app.
Three Basic Principles Of Redux
According to what the documentation say, three basic principles of redux are:
1. Single source of truth( single store )
2. State is read-only
3. Changes are made with pure functions (reducers)
For implementing the redux into our search app we will use react-redux library.
Lets Talk About Three Primary Modules Of React-Redux
Store
Most important module there all application data (or state) is stored:
initial state:
export default {
results: [],
loading: false
}
...
...
...
const rootReducer = combineReducers({
results: searchResults,
loading
});
export default rootReducer;
...
...
...
export default function configureStore(initialState) {
return createStore(
rootReducer,
initialState,
applyMiddleware(thunk, reduxImmutableStateInvariant())
);
}
Actions
A way by which components can "talk" with store, explaining what exactly gonna happen.
search action:
export function loadResultsSuccess(results) {
return { type: 'LOAD_RESULTS_SUCCESS', results};
}
export function loadResults(query) {
return function(dispatch) {
let url = "https://api.github.com/search/repositories?q="+query+"+language:typescript&sort=stars&order=desc";
return fetch(url)
.then(function(response) {
return response.json();
})
.then((result) => {
let results;
if (result.items.length !== 0) {
results = result.items.slice(0,5);
} else {
results = [];
}
//DISPATCH RESULTS
dispatch(loadResultsSuccess(results));
});
};
}
Reducers
Should get the info from action and return new state object which generated from the original state, but without mutating it.
import initialState from './initialState';
export default function searchReducer(state = initialState.results, action) {
switch (action.type) {
case 'LOAD_RESULTS_SUCCESS':
return action.results;
default:
return state;
}
}
Make The Appllication To Work With Stuff Was Just Created
Lest modify our SearchPage so, it will dispatch "search" action instead of calling "loadResults" method (which duty was to load the search results from the request and put the to the state):
SearchPage component:
import React, { Component, PropTypes } from 'react'
import SearchBar from './mySearchBar';
import ResultsList from './myResultsList';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as searchActions from './actions/actionSearch';
class SearchPage extends Component {
constructor(props) {
super(props)
}
handleSearchTextChange(txt) {
this.props.loadResults(txt);//<---HERE
}
render() {
const {results, loading} = this.props;
return (
<div>
<SearchBar onChange={this.handleSearchTextChange.bind(this)}/>
<ResultsList results={results} loading={loading}/>
</div>
);
}
};
function mapStateToProps(state, ownProps) {
return {
results: state.results,
loading: state.loading
};
}
function mapDispatchToProps(dispatch) {
return {
loadResults: bindActionCreators(searchActions.loadResults, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(SearchPage);
See the full code on the repo