JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.0.4/redux.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/0.10.1/fetch.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
<div class="jumbotron">
<div class="container">
<h1>Redux Thunk middleware example</h1>
</div>
</div>
<div class="container">
<form action="" class="form form-inline row">
<div class="form-group">
<input type="text" placeholder="Enter github username" class="form-control" id="myInput" />
</div>
<button class="btn btn-primary" type="submit">load</button>
</form>
<div id="loading" class="row alert alert-info hide">
<i class="fa fa-spin fa-cog"></i> ...loading repos...
</div>
<div class="row">
<ul class="list-group"></ul>
</div>
</div>
CSS
form {
margin-bottom: 15px;
}
JavaScript
console.clear();
// Thunk middleware
// source: https://github.com/gaearon/redux-thunk/blob/master/src/index.js
function thunkMiddleware(store) {
return function(next) {
return function(action) {
if (typeof action === "function") {
return action(store.dispatch, store.getState);
} else {
return next(action);
}
}
}
}
// Action creators
function addReposAction(jsonResult) {
return {
type: "ADD_TWEETS",
repos: jsonResult
};
}
function userChangedAction(value) {
return {
type: "USER_CHANGED",
value: value
};
}
// returns a function and will be called in the Redux-Thunk middleware
function loadReposAction() {
return function(dispatch, getState) {
var state = getState();
var url = "https://api.github.com/users/" + state.user + "/repos";
dispatch(loadingChangedAction(true));
return fetch(url)
.then(function(result) {
dispatch(loadingChangedAction(false));
if (result.status === 200) {
return result.json();
}
throw "request failed";
})
.then(function(jsonResult) {
dispatch(addReposAction(jsonResult));
})
.catch(function(err) {
sweetAlert("Oops...", "Couldn't fetch repos for user: " + state.user, "error");
});
}
}
function loadingChangedAction(isLoading) {
return {
type: "IS_LOADING",
isLoading: isLoading
}
}
// Reducers
function addTweets(state, action) {
return {
isLoading: state.isLoading,
user: state.user,
repos: action.repos
}
}
function userChanged(state, action) {
return {
user: action.value,
repos: [],
isLoading: state.isLoading
};
}
function isLoadingChanged(state, action) {
return {
user: state.user,
repos: state.repos,
isLoading: action.isLoading
};
}
function initialState() {
return {
user: "",
repos: [],
isLoading: false
}
}
function rootReducer(state, action) {
var previousState = (state ?...