I've utilized redux-promise-middleware with react and redux to build an application that has several buttons (each will have its own unique ajax request that will update the state accordingly)
I started to make the dataReducer for three of the many buttons I'm making. dataReducer is already over 100 lines and its also very tedious to make this reducer for the remainder of the buttons.
Is there a more efficient way of creating this dataReducer function and shortening while ensuring that the dataReducer function remains pure
const dataReducer = (state = dataInitialState, action) => {
console.log({ action_type: action.type });
switch (action.type) {
case "UPDATE_URL_ONE_PENDING":
return {
...state,
url_one: {
...state["url_one"],
error: false,
success: false,
loading: true
}
};
case "UPDATE_URL_ONE_FULFILLED":
console.log({ payload: action["payload"] });
return {
...state,
url_one: {
...state["url_one"],
error: false,
success: true,
loading: false,
payload: action["payload"]
}
};
case "UPDATE_URL_ONE_REJECTED":
return {
...state,
url_one: {
...state["url_one"],
error: true,
success: false,
loading: false
}
};
case "UPDATE_URL_TWO_PENDING":
return {
...state,
url_two: {
...state["url_two"],
error: false,
success: false,
loading: true
}
};
case "UPDATE_URL_TWO_FULFILLED":
return {
...state,
url_two: {
...state["url_two"],
error: false,
success: true,
loading: false,
payload: action["payload"]
}
};
case "UPDATE_URL_TWO_REJECTED":
return {
...state,
url_two: {
...state["url_two"],
error: true,
success: false,
loading: false
}
};
case "UPDATE_URL_THREE_PENDING":
return {
...state,
url_three: {
...state["url_three"],
error: false,
success: false,
loading: true
}
};
case "UPDATE_URL_THREE_FULFILLED":
return {
...state,
url_three: {
...state["url_three"],
error: false,
success: true,
loading: false,
payload: action["payload"]
}
};
case "UPDATE_URL_THREE_REJECTED":
return {
...state,
url_three: {
...state["url_three"],
error: true,
success: false,
loading: false
}
};
default:
return state;
}
};
Full Code (Code Sandbox Here)
import React from "react";
import ReactDOM from "react-dom";
import { Provider, connect } from "react-redux";
import { createStore, applyMiddleware, combineReducers } from "redux";
import thunk from "redux-thunk";
import promise from "redux-promise-middleware";
//Action Creator
function updateData(url, type) {
console.log({ url, type });
return dispatch => {
dispatch({
type: type,
payload: $.ajax({
type: "GET",
url: url,
dataType: "json",
async: false
})
});
};
}
//App Component
class App extends React.Component {
render() {
return (
<div>
<button
onClick={() => {
console.log({ props: this.props });
}}
>
Check Props
</button>
<button
onClick={() => {
this.props.updateData(
"https://api.iextrading.com/1.0/stock/market/batch?symbols=TSLA&types=quote,stats,news,chart&range=1m&last=5",
"UPDATE_URL_ONE"
);
}}
>
UPDATE URL ONE
</button>
<button
onClick={() => {
this.props.updateData(
"https://api.iextrading.com/1.0/stock/market/batch?symbols=GE&types=quote,stats,news,chart&range=1m&last=5",
"UPDATE_URL_TWO"
);
}}
>
UPDATE_URL_TWO
</button>
<button
onClick={() => {
this.props.updateData(
"https://api.iextrading.com/1.0/stock/market/batch?symbols=PZZA&types=quote,stats,news,chart&range=1m&last=5",
"UPDATE_URL_THREE"
);
}}
>
UPDATE_URL_THREE
</button>
<button
onClick={() => {
this.props.updateData(
"https://api.iextrading.com/1.0/stock/market/batch?symbols=PZZA&types=quote,stats,news,chart&range=1m&last=5",
"UPDATE_URL_FOUR"
);
}}
>
UPDATE_URL_FOUR
</button>
<button
onClick={() => {
this.props.updateData(
"https://api.iextrading.com/1.0/stock/market/batch?symbols=PZZA&types=quote,stats,news,chart&range=1m&last=5",
"UPDATE_URL_FIVE"
);
}}
>
UPDATE_URL_FIVE
</button>
<button
onClick={() => {
this.props.updateData(
"https://api.iextrading.com/1.0/stock/market/batch?symbols=PZZA&types=quote,stats,news,chart&range=1m&last=5",
"UPDATE_URL_SIX"
);
}}
>
UPDATE_URL_SIX
</button>
<button
onClick={() => {
this.props.updateData(
"https://api.iextrading.com/1.0/stock/market/batch?symbols=PZZA&types=quote,stats,news,chart&range=1m&last=5",
"UPDATE_URL_SEVEN"
);
}}
>
UPDATE_URL_SEVEN
</button>
<button
onClick={() => {
this.props.updateData(
"https://api.iextrading.com/1.0/stock/market/batch?symbols=PZZA&types=quote,stats,news,chart&range=1m&last=5",
"UPDATE_URL_EIGHT"
);
}}
>
UPDATE_URL_EIGHT
</button>
<button
onClick={() => {
this.props.updateData(
"https://api.iextrading.com/1.0/stock/market/batch?symbols=PZZA&types=quote,stats,news,chart&range=1m&last=5",
"UPDATE_URL_NINE"
);
}}
>
UPDATE_URL_NINE
</button>
<button
onClick={() => {
this.props.updateData(
"https://api.iextrading.com/1.0/stock/market/batch?symbols=PZZA&types=quote,stats,news,chart&range=1m&last=5",
"UPDATE_URL_TEN"
);
}}
>
UPDATE_URL_TEN
</button>
</div>
);
}
}
const mapStateToProps = state => state;
const mapDispatchToProps = dispatch => {
return {
updateData: (data, type) => {
dispatch(updateData(data, type));
}
};
};
const AppEnhanced = connect(
mapStateToProps,
mapDispatchToProps
)(App);
//reducer below that will determine how the state updates based on the action reducer above
const dataInitialState = {
url_one: { error: false, success: false, loading: true, payload: [] },
url_two: { error: false, success: false, loading: true, payload: [] },
url_three: { error: false, success: false, loading: true, payload: [] },
url_four: { error: false, success: false, loading: true, payload: [] },
url_five: { error: false, success: false, loading: true, payload: [] },
url_size: { error: false, success: false, loading: true, payload: [] },
url_seven: { error: false, success: false, loading: true, payload: [] },
url_eight: { error: false, success: false, loading: true, payload: [] },
url_nine: { error: false, success: false, loading: true, payload: [] },
url_ten: { error: false, success: false, loading: true, payload: [] }
};
const dataReducer = (state = dataInitialState, action) => {
console.log({ action_type: action.type });
switch (action.type) {
case "UPDATE_URL_ONE_PENDING":
return {
...state,
url_one: {
...state["url_one"],
error: false,
success: false,
loading: true
}
};
case "UPDATE_URL_ONE_FULFILLED":
console.log({ payload: action["payload"] });
return {
...state,
url_one: {
...state["url_one"],
error: false,
success: true,
loading: false,
payload: action["payload"]
}
};
case "UPDATE_URL_ONE_REJECTED":
return {
...state,
url_one: {
...state["url_one"],
error: true,
success: false,
loading: false
}
};
case "UPDATE_URL_TWO_PENDING":
return {
...state,
url_two: {
...state["url_two"],
error: false,
success: false,
loading: true
}
};
case "UPDATE_URL_TWO_FULFILLED":
return {
...state,
url_two: {
...state["url_two"],
error: false,
success: true,
loading: false,
payload: action["payload"]
}
};
case "UPDATE_URL_TWO_REJECTED":
return {
...state,
url_two: {
...state["url_two"],
error: true,
success: false,
loading: false
}
};
case "UPDATE_URL_THREE_PENDING":
return {
...state,
url_three: {
...state["url_three"],
error: false,
success: false,
loading: true
}
};
case "UPDATE_URL_THREE_FULFILLED":
return {
...state,
url_three: {
...state["url_three"],
error: false,
success: true,
loading: false,
payload: action["payload"]
}
};
case "UPDATE_URL_THREE_REJECTED":
return {
...state,
url_three: {
...state["url_three"],
error: true,
success: false,
loading: false
}
};
default:
return state;
}
};
const reducers = combineReducers({
data: dataReducer
});
const store = createStore(reducers, applyMiddleware(thunk, promise));
ReactDOM.render(
<Provider store={store}>
<AppEnhanced />
</Provider>,
document.getElementById("root")
);
A lot of your code can be reduced to a single reusable component that updates its own local
stateaccording to the success or failure of theajaxrequest. Too often developers run toreduxwithout understanding why. In this case/example, you don't need it. However, if your application was heavily nested and split across multiple parent components, thenreduxcould be a viable option. Either way, it can still be reduced to a single reusable component.Working example: https://codesandbox.io/s/0x0478x4wp
index.js
components/StockButton
components/Placeholder