I want to remove item(product) in React-Reduxenter code here
ProdcutType.js
export const ADD_TO_CART = 'ADD_TO_CART'
export const REMOVE_ITEM = 'REMOVE_ITEM'
ProdcutAction.js
import { ADD_TO_CART, REMOVE_ITEM } from "./ProductType";
export const add_to_cart = (img, title, price) => {
return {
type: ADD_TO_CART,
img, title, price
}
}
export const remove_item = (index) => {
return {
type: REMOVE_ITEM,
index
}
}
ProductReducer.js
import { ADD_TO_CART, REMOVE_ITEM } from "./ProductType";
enter code hereconst initialState = {
arrProdcut: [],
}
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TO_CART: return {
...state,
arrProdcut: state.arrProdcut.concat({
img: action.img,
title: action.title,
price: action.price
})
}
case REMOVE_ITEM: {
// const item = action.item;
// const new_state = { ...state };
// delete new_state.arrProdcut[item];
// return new_state;
return {
...state,
arrProdcut: state.arrProdcut.filter(item => item.id != action.index)
}
}
default:
return state;
}
}
export default rootReducer
cart.js
import React, { useEffect } from 'react'
import styled from 'styled-components'
import { useParams } from 'react-router'
import { useSelector } from 'react-redux';
import { remove_item } from './redux/ProductAction'
import { connect } from 'react-redux'
import { Delete } from '#mui/icons-material';
import Cart2 from './Cart2';
function Cart(props) {
const products = useSelector(state => state.arrProdcut)
return (
<Contanier>
<Content>
{products.map((item, index) => (
<Prodcts>
<Cart2 item={item} key={item.id} />
</Prodcts>
))}
</Content>
</Contanier >
)
}
export default Cart
cart2.js
import React, { useEffect } from 'react'
import styled from 'styled-components'
import { useParams } from 'react-router'
import { useSelector } from 'react-redux';
import { remove_item } from './redux/ProductAction'
import { connect } from 'react-redux'
import { Delete } from '#mui/icons-material';
function Cart2(props) {
const { item, index } = props;
return (
<Contanier>
<Content>
<Prodcts>
<div>
<h3>Product</h3>
<Divimg>
<img src={item.img} />
</Divimg>
</div>
<div>
<h3>Name product</h3>
<h4>{item.title}</h4>
</div>
<div>
<h3>Price</h3>
<h4>${item.price}</h4>
</div>
<div>
<h3>Quantity</h3>
<input type="number" />
</div>
<div>
<h3>Remove</h3>
<button onClick={() => props.remove_item(item.id)}>
Delete
</button>
</div>
</Prodcts>
</Content>
</Contanier >
)
}
const MapToDispatch = dispatch => {
return {
remove_item: (id) => dispatch(remove_item(id))
} } export default connect(null, MapToDispatch)(Cart2)
Related
I am new to react redux toolkit and redux-saga and have encountered an error where it only renders the last api call value from moviedb api. Also when I console log the state from useSelector, it renders multiple values. Here's my code
App.js
import "./App.css";
import Row from "./components/Row";
import requests from "./requests";
function App() {
return (
<div className="App">
<Row
title="Netflix Originals"
fetchUrl={requests.fetchNetflixOriginals}
/>
<Row title="Trending Now" fetchUrl={requests.fetchTrending} />
{/* <Row title="Top Rated" fetchUrl={requests.fetchTopRated} />
<Row title="Action Movies" fetchUrl={requests.fetchActionMovies} />
<Row title="Horror Movies" fetchUrl={requests.fetchHorrorMovies} /> */}
</div>
);
}
export default App;
Store.js
import { configureStore, combineReducers } from "#reduxjs/toolkit";
import createSagaMiddleware from "redux-saga";
import { watcherSaga } from "./sagas/rootSaga";
import movieReducer from "./ducks/movieSlice";
const sagaMiddleware = createSagaMiddleware();
const reducer = combineReducers({
movie: movieReducer,
});
const store = configureStore({
reducer,
middleware: [sagaMiddleware],
});
sagaMiddleware.run(watcherSaga);
export default store;
movieSlice.js
import { createSlice } from "#reduxjs/toolkit";
const movieSlice = createSlice({
name: "movie",
initialState: [],
reducers: {
getMovie() {},
setMovie(state, action) {
const movieData = action.payload;
return { ...state, ...movieData };
},
},
});
export const { getMovie, setMovie } = movieSlice.actions;
export default movieSlice.reducer;
rootSaga.js
import { takeEvery, takeLatest } from "redux-saga/effects";
import { getMovie } from "../ducks/movieSlice";
import { handleGetMovie } from "./handlers/movies";
export function* watcherSaga() {
yield takeEvery(getMovie.type, handleGetMovie);
}
handler
movie.js
import { call, put } from "redux-saga/effects";
import { requestGetMovie } from "../requests/movies";
import { setMovie } from "../../ducks/movieSlice";
export function* handleGetMovie(action) {
try {
const response = yield call(requestGetMovie, action.payload);
const { data } = response;
yield put(setMovie(data));
} catch (error) {
console.log(error);
}
}
requests
movie.js
import axios from "axios";
const baseURL = "https://api.themoviedb.org/3";
export function requestGetMovie(url) {
const URL = baseURL + url.fetchLink;
return axios.request({
method: "get",
url: URL,
});
}
requests.js
const APIKEY = "9cf4e09bc69e9849477a8ac79d29a205";
const requests = {
fetchTrending: `/trending/all/week?api_key=${APIKEY}&language=en=us`,
fetchNetflixOriginals: `/discover/tv?api_key=${APIKEY}&with_networks=213`,
fetchTopRated: `/movie/top_rated?api_key=${APIKEY}&language=en=us`,
fetchActionMovies: `/discover/movie?api_key=${APIKEY}&with_generes=28`,
fetchHorrorMovies: `/discover/movie?api_key=${APIKEY}&with_genres=27
`,
};
export default requests;
Row.js
import React, { useState, useEffect } from "react";
import styled from "styled-components";
import { useDispatch, useSelector } from "react-redux";
import { getMovie } from "../redux/ducks/movieSlice";
function Row({ title, fetchUrl }) {
const dispatch = useDispatch();
useEffect(() => {
dispatch(
getMovie({
fetchLink: fetchUrl,
})
);
}, [dispatch, fetchUrl]);
const movie = useSelector((state) => {
return state.movie.results;
});
console.log(movie);
return (
<RowContainer>
{title}
<CardsContainer>{movie && movie[0].name}</CardsContainer>
</RowContainer>
);
}
export default Row;
const RowContainer = styled.div`
color: white;
`;
const CardsContainer = styled.div`
color: white;
`;
Netflix orginals should display Lucifer while it renders Money Heist from the latest state value and also if i console.log the movie value, multiple values are repeated even if i have only two row component on app.js. If i have Row component on app.js 5 times, it displays the value 25 times on console.
image
image2
Your problem lies on the file movieSlice.js, exactly here:
setMovie(state, action) {
const movieData = action.payload;
return { ...state, ...movieData };
}
You are overriding the movie object everytime you call the setMovie action.
What you should do insted is to have separate actions for different movie types like this:
const movieSlice = createSlice({
name: "movie",
initialState: {
trendingMovies: [],
actionMovies: [],
},
reducers: {
setTrendingMovies(state, action) {
state.trendingMovies = action.payload;
},
setActionMovies(state, action) {
state.actionMovies = action.payload;
}
},
});
console.log function in HelloWorld function is showing updated state so why is paragraph in render function not updating? I can't seem to be able to fix render not updating.
Code:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {configureStore} from '#reduxjs/toolkit';
var initialState = {value: 0};
function counterReducer(state=initialState,action) {
if(action.type === 'counter/increment') {
return {
...state,
value: state.value + 1
}
} else {
return state;
}
}
const store = configureStore({reducer: counterReducer});
store.dispatch({type: 'counter/increment'});
class Counter extends React.Component {
HelloWorld = () => {
store.dispatch({type: 'counter/increment'});
console.log(store.getState().value);
}
render() {
return (
<div>
<p>{store.getState().value}</p>
<button onClick={this.HelloWorld}>Add</button>
</div>
);
}
}
ReactDOM.render(<Counter />,document.getElementById('root'));
I have to use 'React-Redux' with #ReduxJS/toolkit to get render() function to update webpage. To get ReduxJS/toolkit to update webpage without 'React-Redux'? Answer: You use store.subscribe() function instead, for eg)
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {configureStore} from '#reduxjs/toolkit';
var initialState = {value: 0};
function counterReducer(state=initialState,action) {
if(action.type === 'counter/increment') {
return {
...state,
value: state.value + 1
}
} else {
return state;
}
}
const store = configureStore({reducer: counterReducer});
class Counter extends React.Component {
HelloWorld = () => {
store.dispatch({type: 'counter/increment'});
console.log(store.getState().value);
}
render() {
return (
<div>
<p id="update"></p>
<button onClick={this.HelloWorld}>Add</button>
</div>
);
}
}
function Two() {
document.getElementById("update").innerHTML = store.getState().value;
}
store.subscribe(Two);
ReactDOM.render(<Counter />,document.getElementById('root'));
More information Why
Here's how to do ReduxJS/toolkit with React-Redux:
import React from 'react';
import ReactDOM from 'react-dom';
import {configureStore} from '#reduxjs/toolkit';
import {Provider,useSelector} from 'react-redux';
var initialState = {value: 0};
function counterReducer(state=initialState,action) {
if(action.type === 'counter/increment') {
return {
...state,
value: state.value+1
};
}
return state;
}
const store = configureStore({reducer: counterReducer});
function Counter() {
function HelloWorld() {
store.dispatch({type: 'counter/increment'});
}
let x = useSelector((state) => state.value);
return (
<div>
<p>{x}</p>
<button onClick={HelloWorld}>Add</button>
</div>
);
}
ReactDOM.render(
<Provider store={store}>
<Counter />
</Provider>,
document.getElementById('root')
);
To do answer the mapStateToProps (old fashioned way)?
import React from 'react';
import ReactDOM from 'react-dom';
import {configureStore} from '#reduxjs/toolkit';
import {Provider,connect} from 'react-redux';
var initialState = {value: 0};
function counterReducer(state=initialState,action) {
if(action.type === 'counter/increment') {
return {
...state,
value: state.value+1
};
}
return state;
}
const store = configureStore({reducer: counterReducer});
function Counter(props) {
function HelloWorld() {
store.dispatch({type: 'counter/increment'});
}
return (
<div>
<p>{props.x}</p>
<button onClick={HelloWorld}>Add</button>
</div>
);
}
const mapStateToProps = (state) => ({
x: state.value
})
Counter = connect(mapStateToProps)(Counter);
ReactDOM.render(
<Provider store={store}>
<Counter />
</Provider>,
document.getElementById('root')
);
How to do mapDispatchToProps?
import React from 'react';
import ReactDOM from 'react-dom';
import {configureStore} from '#reduxjs/toolkit';
import {Provider,connect} from 'react-redux';
var initialState = {value: 0};
function counterReducer(state=initialState,action) {
if(action.type === 'counter/increment') {
return {
...state,
value: state.value+1
};
}
return state;
}
const store = configureStore({reducer: counterReducer});
function Counter(props) {
return (
<div>
<p>{props.x}</p>
<button onClick={props.HelloWorld}>Add</button>
</div>
);
}
const mapStateToProps = (state) => ({
x: state.value
})
const mapDispatchToProps = (dispatch) => ({
HelloWorld: () => {dispatch({type: 'counter/increment'})}
})
Counter = connect(mapStateToProps,mapDispatchToProps)(Counter);
ReactDOM.render(
<Provider store={store}>
<Counter />
</Provider>,
document.getElementById('root')
);
I'm new to redux (and stack-overflow) and am having some issues with my search functionality. Originally it was working fine with data that I manually set, but then I imported Data from an API and I cannot get the search to work now. Any help or advice would be much appreciated!
<-- actions -->
//fetchData.js
import {
FETCH_DATA_REQUEST,
FETCH_DATA_SUCCESS,
FETCH_DATA_FAILURE,
SEARCH_POSTS
} from './types';
export const fetchData = () => {
return (dispatch) => {
dispatch(fetchDataRequest())
axios
.get("https://hn.algolia.com/api/v1/search?query=redux")
.then(response => {
const posts = response.data
dispatch(fetchDataSuccess(posts))
})
.catch(error => {
dispatch(fetchDataFailure(error.message))
})
}
}
export const fetchDataRequest = () => {
return {
type: FETCH_DATA_REQUEST
}
}
const fetchDataSuccess = posts => {
return {
type: FETCH_DATA_SUCCESS,
payload: posts
}
}
const fetchDataFailure = error => {
return {
type: FETCH_DATA_FAILURE,
payload: error
}
}
export function searchData(value) {
return {
type: SEARCH_POSTS,
payload: value
}
}
<--- components --->
//dataContainer.js
import { connect } from 'react-redux';
import { fetchData } from '../actions/fetchData';
import { Card } from 'react-bootstrap';
import { Button } from 'react-bootstrap';
function DataContainer({ results, fetchData }) {
useEffect(() => {
fetchData()
}, [])
return results.loading ? (
<h2>Loading...</h2>
) : results.error ? (
<h2>{results.error}</h2>
) : (
<div>
<h1>Posts</h1>
{results && results.posts && results.posts.map(result =>
<div className ="cardDiv" key={result.objectID}>
<Card>
<Card.Header>By: {result.author}</Card.Header>
<Card.Body>
<Card.Title>{result.title}</Card.Title>
<Card.Text>
{result.body}
</Card.Text>
<Button variant="primary" href={result.url}>See Article</Button>
</Card.Body>
</Card>
{'\n'}
</div>)}
</div>
)
}
const mapStateToProps = state => {
return {
results: state.data
}
}
const mapDispatchToProps = dispatch => {
return {
fetchData: () => dispatch(fetchData())
}
}
export default connect(mapStateToProps, mapDispatchToProps)(DataContainer);
//searchBar.js
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { searchData, fetchData } from '../actions/fetchData';
function SearchBar({ posts, fetchData}) {
useEffect(() => {
fetchData()
}, [])
const { search, value } = posts;
return (
<input
className="form-control mx-auto"
placeholder="Search"
onChange={(e) => searchData(e.target.value)}
value={value}
style={{ maxWidth: '200px', textAlign: 'center' }} />
);
}
function mapStateToProps({ posts, state }) {
return {
posts: state.posts,
value: posts.value
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({ searchData, fetchData }, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(SearchBar);
//homePage.js
import SearchBar from './searchBar';
import DataContainer from './dataContainer';
import { connect } from 'react-redux';
import * as actions from '../actions/fetchData';
class HomePage extends Component {
handleSearchBarSubmit(query) {
this.props.fetchPostsWithQuery(query, () => {
this.props.history.push('/results');
});
}
render() {
return (
<div className="home">
<SearchBar page="home"/>
<DataContainer/>
</div>
);
}
}
export default connect(null, actions)(HomePage);
<--- Reducers --->
//dataReducer
FETCH_DATA_REQUEST,
FETCH_DATA_SUCCESS,
FETCH_DATA_FAILURE,
SEARCH_POSTS
} from "../actions/types";
const _ = require('lodash')
const posts = []
const initState = {
loading: false,
posts,
error: '',
filtered: []
}
const reducer = (state = initState, action) => {
switch (action.type) {
case FETCH_DATA_REQUEST:
return {
...state,
loading: true
}
case FETCH_DATA_SUCCESS:
return {
loading: false,
posts: action.payload.hits,
filtered: action.payload.hits,
error: ''
}
case FETCH_DATA_FAILURE:
return {
loading: false,
posts: [],
error: action.payload
}
case SEARCH_POSTS:
const { payload } = action
const filtered = _.filter(state.data.posts, (o) => _.toLower(o.post).includes(_.toLower(payload)))
return {
...state,
filtered
}
default: return state
}
}
export default reducer;
//searchReducer.js
SEARCH_POSTS
} from '../actions/types';
const posts = []
const INIT_STATE = {
posts
}
export default function (state = INIT_STATE, action) {
switch (action.type) {
case SEARCH_POSTS: {
let { value } = action.payload.hits;
const posts = state.posts.filter((post) => post.title.toLowerCase().includes(state.value.toLowerCase()));
return { ...state, value, posts };
}
default:
return state;
}
}
//rootReducer.js
import { combineReducers } from 'redux';
import { reducer as form } from 'redux-form'
import resultsPosts from './searchReducer';
const rootReducer = combineReducers({
data: dataReducer,
resultsPosts,
form
})
export default rootReducer;
<--- App.js and Index.js --->
//app.js
import './App.css';
import HomePage from './components/homePage';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import ResultPage from './components/resultPage'
function App() {
return (
<BrowserRouter>
<div className='App'>
<h1 style={{textAlign: 'center'}}>Search for Hacker News!</h1>
<Switch>
<Route path="/" exact={true} component={HomePage} />
<Route path='/results/:id' component={ResultPage}/>
</Switch>
</div>
</BrowserRouter>
);
}
export default App;
//index.js
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { Provider } from 'react-redux';
import store from './store';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
serviceWorker.unregister();
I am trying to combine navigation, more exactly stack navigation with my react native redux application, and I encountered this error during debugging. From what I've already searched, it's because the navigation isn't really compatible with the redux mode of work. So I tried a solution to my problem, but still I have the same error. Here is my code:
Login.js
import React, { Component } from 'react';
import { View, ActivityIndicator, TouchableHighlight } from 'react-native';
import { getLogger, issueToText } from '../core/utils';
import styles from '../core/styles';
import { Card, Button, FormLabel, FormInput } from "react-native-elements";
import { connect } from 'react-redux'
import { loginAction } from '../actions/LoginActions'
class LoginComponent extends Component {
constructor(props) {
super(props);
this.login = this.login.bind(this)
}
render() {
const { error, isLoading } = this.props;
const inputFormProp = {
username: '',
password: ''
};
return (
<View style={{ paddingVertical: 20 }}>
<Card>
<FormLabel>Email</FormLabel>
<FormInput value={inputFormProp.username} onChangeText={(text) => inputFormProp.username = text} />
<FormLabel>Password</FormLabel>
<FormInput value={inputFormProp.password} onChangeText={(text) => inputFormProp.password = text} />
<Button
buttonStyle={{ marginTop: 20 }}
backgroundColor="#03A9F4"
title="SIGN IN"
onPress={this.login(inputFormProp)}
/>
</Card>
<ActivityIndicator animating={this.props.isLoading} style={styles.activityIndicator} size="large" />
</View>
);
}
login(inputFormProp) {
console.log(this.props)
const { store } = this.props.screenProps.store;
console.log(loginAction)
const { dispatch } = this.props
console.log(dispatch)
dispatch(loginAction(inputFormProp))
.then(() => {
if (this.props.error === null && this.props.isLoading === false) {
if (store.getState().auth.token) {
this.props.navigation.navigate('ProductList', { token: store.getState().auth.token });
}
}
})
.catch(error => {
});
}
}
function mapStateToProps(state) {
const { error, isLoading } = state.auth
return {
error,
isLoading,
}
}
export default connect(mapStateToProps)(LoginComponent)
App.js
import React, { Component } from 'react';
import { createStore, applyMiddleware, combineReducers, compose } from 'redux';
import { createLogger } from 'redux-logger';
import thunk from 'redux-thunk';
import { authReducer } from "./src/reducers/LoginReducer";
import { productReducer } from "./src/product/service";
import { ProductList } from "./src/product/ProductList";
import { LoginComponent } from "./src/components/Login";
import { Provider, connect } from "react-redux";
import { StackNavigator, addNavigationHelpers } from "react-navigation";
import Routes from "./src/core/routes";
const AppNavigator = StackNavigator(Routes, {
navigationOptions: {
title: ({ state }) => {
if (state.params) {
return `${state.params.title}`;
}
}
}
});
const navReducer = (state, action) => {
const newState = AppNavigator.router.getStateForAction(action, state);
return newState || state;
};
#connect(state => ({
nav: state.nav
}))
class AppWithNavigationState extends Component {
render() {
return (
<AppNavigator
navigation={addNavigationHelpers({
dispatch: this.props.dispatch,
state: this.props.nav
})}
/>
);
}
}
const initialState = {
auth: { isLoading: false, error: null },
};
const rootReducer = combineReducers({ product: productReducer, auth: authReducer, nav: navReducer });
let store = createStore(rootReducer, initialState,
compose(applyMiddleware(thunk, createLogger())));
export default function App() {
return (
<Provider store={store}>
<AppWithNavigationState />
</Provider>
);
}
Routes.js
import { ProductList } from "../product/ProductList";
import { LoginComponent } from "../components/Login";
const Routes = {
Login: { screen: LoginComponent },
ProductList: { screen: ProductList }
};
export default Routes;
Here is my error: Route Login should declare a screen.
What did I do wrong with my code? Thank you.
I fixed the error. It was because I added between LoginComponent {} in the routes.js file at:
import { LoginComponent } from "../components/Login";
I try to add more props to existing list i am able to fire dispatch action but reducer doesn't get trigger
i have my headercontainer.js file like
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { fetchAccount } from 'actions/account'
import { getAccount } from 'reducers/account'
import { fetchCart } from 'actions/cart'
import { getCart } from 'reducers/cart'
//import * as cls from 'actions/cls'
import { getReadmore } from 'reducers/cls'
import * as cls from 'actions/cls'
import { fetchAuthenticityToken } from 'actions/authenticityToken'
import { getAuthenticityToken } from 'reducers/authenticityToken'
import Header from 'components/Header'
class HeaderContainer extends Component {
static propTypes = {
account: PropTypes.object,
authenticityToken: PropTypes.object,
cart: PropTypes.object,
dispatch: PropTypes.func
}
componentDidMount() {
if (typeof document !== 'undefined') {
if (!this.props.account.isFetching) {
this.props.dispatch(fetchAccount())
}
if (!this.props.authenticityToken.isFetching) {
this.props.dispatch(fetchAuthenticityToken())
}
if (!this.props.cart.isFetching) {
this.props.dispatch(fetchCart())
}
}
}
constructor(props) {
super(props);
this.state = {classToSend: true };
}
stateToRender(){
(this.state.classToSend) ? this.setState({classToSend: false}) : this.setState({classToSend: true});
}
onClickHandler(){
this.stateToRender();
let action = cls.readMore(this.state.classToSend)
this.props.dispatch(action)
// this.props.readMore(this.state.classToSend);
}
render() {
const { account, cart, authenticityToken } = this.props
if(!account || !cart) {
return false
}
return (
<div id ="cvb">
<div id="toggle-nav" className={this.state.toggleClass?'visible-xs nav-open':'visible-xs'} onClick={() => this.onClickHandler()} >
<span data-action="toggle-nav" className="action mt-menu-label">
<span className="mt-menu-bread mt-menu-bread-top">
<span className="mt-menu-bread-crust mt-menu-bread-crust-top"></span>
</span>
<span className="mt-menu-bread mt-menu-bread-middle">
<span className="mt-menu-bread-crust mt-menu-bread-crust-middle"></span>
</span>
<span className="mt-menu-bread mt-menu-bread-bottom">
<span className="mt-menu-bread-crust mt-menu-bread-crust-bottom"></span>
</span>
</span>
</div>
<Header account={account} cart={cart} />
</div>
)
}
}
const mapStateToProps = (state) => {
return {
account: getAccount(state),
cart: getCart(state),
classToSend: getReadmore(state),
authenticityToken: getAuthenticityToken(state)
}
}
export default connect(mapStateToProps)(HeaderContainer)
My cls.js reducer
export function getReadmore(state) {
console.log(state.readMore1)
console.log("are yar")
return state.readMore1
}
export function readMore1 (state="", action) {
console.log(action.type)
switch(action.type){
case READ_MORE:
return action.payload;
}
return state;
}
cls.js Action
export function readMore(class_something) {
const READ_MORE = 'READ_MORE';
console.log("--------------------------")
console.log(class_something)
return {
type: READ_MORE,
payload: class_something
};
}
Though i am able to call action cls.js file but reducer not getting trigger
can anyone help me to get out of this trouble.
My edits
my index.js in reducer folder
import { combineReducers } from 'redux'
import { reducer as form } from 'redux-form'
import { routerReducer } from 'react-router-redux'
import { currency } from './currency'
import { cart } from './cart'
import { account } from './account'
import { alerts } from './alerts'
import { login } from './login'
import { authenticityToken } from './authenticityToken'
import { products } from './products'
import { product } from './product'
const routing = routerReducer
const rootReducer = combineReducers({
form,
routing,
currency,
cart,
cls,
account,
alerts,
authenticityToken,
login,
products,
product
})
export default rootReducer
Your case in your reducer file should be "READ_MORE" (with quotations) not READ_MORE (without quotations).