I am trying to make a simple exercise for react-redux to understand the process but somehow I am stuck .. any help would be really appreciate.
The interesting part is when I do subscribe and try to log store into the console, it works and shows me updated value but I am not able to select it using useSelector
Also with the help of Dev tool's i could see the state being changed from INIT to ADD_USER..
Below are my components files and reducers.
App.js
import React from "react";
import { Provider } from "react-redux";
import store from "./stores/store";
import { HomePage } from "./components/containers/HomePage";
function App() {
return (
<Provider store={ store }>
<HomePage/>
</Provider>
);
}
export default App;
HomePage.js. --> Here state.isLogin is not selected.. but the subscribe comment works
import React from "react";
import { Sidebar } from "./Sidebar";
import { LoginPage } from "./LoginPage";
import { useSelector } from "react-redux";
export const HomePage = () => {
const userLogin = useSelector(state => state.isLogin);
// const storeState = store.subscribe (() => console.log(store.getState()));
return (
<div>
<LoginPage />
<Sidebar />
</div>
);
};
LoginPage.js
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import * as action from "../../action/index";
export const LoginPage = (setLogin) => {
const dispatch = useDispatch();
const [name, setName] = useState("");
const createUser = (e) => {
e.preventDefault();
const addUser = {
name: name,
isLogin: true
};
dispatch(action.addUsers(addUser));
};
return (
<div className="card border-0 shadow">
<div className="card-header">Login Here!</div>
<div className="card-body">
<form onSubmit={(e) => createUser(e)}>
<div className="form-group">
<input
type="text"
className="form-control"
placeholder="Enter Your Name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
<button className="btn btn-primary" type="submit">
Create Contact
</button>
</form>
</div>
</div>
);
};
reducers - Index.js and user.js
import userReducer from './users'
import { combineReducers} from "redux";
const allReducers = combineReducers({
addUser : userReducer,
});
export default allReducers;
User.js
import * as types from '../actionTypes/index'
const intialState = {
user: [],
messages : [],
isLogin : false
};
const users = (state = intialState, action) => {
switch (action.type) {
case types.ADD_USER:
return {
...state,
user: [action.payload.name, ...state.user],
isLogin: action.payload.isLogin
};
default:
return state
}
}
export default users;
Store.js
import { createStore } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import allReducers from '../reducers'
const store = createStore(allReducers,composeWithDevTools());
export default store;
Any idea's/Input on what went wrong ? or what is the issue?
Thank you
Try using below code in HomePage
const userLogin = useSelector(state => state.addUser.isLogin);
Related
following is the code that i used in order to manage the state but unfortunately my state is not updating when using redux
the action is as given below:
export let incNumber = ()=>{
return {
type: 'INCREMENT'
}
}
export let decNumber = ()=>{
return {
type: 'DECREMENT'
}
}
while the reducer is as given below:
import mainReducer from "./reducers";
import { createStore } from "redux";
const store = createStore(mainReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
export default store;
the main app.js file is as given below:
import './App.css';
import {useSelector, useDispatch} from 'react-redux';
import {incNumber, decNumber} from './actions/index';
function App() {
let myState = useSelector((state)=> {
return state.changeTheNumber;
});
console.log(myState);
const dispatch = useDispatch();
return (
<>
<div className="main-div">
<div className="container">
<h1>Increment/Decrement counter</h1>
<h4>using React and Redux</h4>
<div className="quantity">
<a className="quantity__minus" title="Decrement" onClick={()=>dispatch(decNumber())}><span>-</span></a>
<input name="quantity" type="text" className="quantity__input" defaultValue={myState}/>
<h1>{myState}</h1>
<a className="quantity__plus" title="Increment" onClick={()=>dispatch(incNumber())}><span>+</span></a>
</div>
</div>
</div>
</>
);
}
export default App;
the code of mainReducer is:
import {combineReducers} from 'redux';
import changeTheNumber from "./upDown";
const mainReducer = combineReducers({
changeTheNumber
})
export default mainReducer;
updown reducer is given as:
const initialState = 0;
const changeTheNumber = (state = initialState, action) => {
switch (action.type) {
case "INCREMENT": return state + 1;
case "DECREMENT": return state - 1;
default: return state;
}
}
export default changeTheNumber;
now the problem is that although as soon as i click on + button, the updated value is being shown on console in the browser but is not updated in the field specified. Any solutions?
My component is not rerendering after the store is changing.
I make sure that the store is actually changing by dropping him to the console with
store.subscribe() and console.log(store.getState()) but still the component is not rerendering again.
I will appreciate your help.
configureStore.js
import { createStore, combineReducers } from 'redux';
import home from '../reducers/home';
import favorites from '../reducers/favorites';
export default () => {
const store = createStore(combineReducers({
home,
favorites
}))
return store;
}
App.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import configureStore from './redux/store/configureStore';
import AppRouter from './router/AppRouter';
const store = configureStore();
const jsx = (
<Provider store={store}>
<AppRouter />
</Provider>
);
ReactDOM.render(jsx, document.querySelector('#root'));
home.js (reducer)
const homeDefaultState = {
name: 'someName'
}
export default (state = homeDefaultState, action) => {
switch (action.type) {
case 'CHANGE_NAME':
return {
...state,
name: 'otherName'
}
default:
return state;
}
}
home.js (action)
export const changeName = () => ({
type: 'CHANGE_NAME'
})
Home.js (component)
import React from 'react';
import configureStore from '../../redux/store/configureStore';
import { changeName } from '../../redux/actions/home';
import { connect } from 'react-redux';
const store = configureStore();
const handleName = () => {
store.dispatch(changeName())
}
const Home = (props) => (
<div className="home">
<button onClick={handleName}>
change name
</button>
{props.home.name}
</div>
);
const mapStateToProps = (state) => ({
home: state.home
});
export default connect(mapStateToProps)(Home);
In your Home component you initialize store for second time. And bound action to this second store
const store = configureStore();
const handleName = () => {
store.dispatch(changeName())
}
At the same time with connect() you access store declared in App.jsx
Read from first but update second. Just remove second store and use mapDispatchToProps(second parameter passed to connect()) instead:
const mapStateToProps = (state) => ({
home: state.home
});
export default connect(mapStateToProps, { handleName: changeName })(Home);
Need some help.
As I am trying to get some understanding of React/REdux global state I made some simple get request.
This is done with Axios, thunk, Redux, but i can't get this working
I have Post.js file, nothing fancy
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import PostForm from './PostForm';
export class Post extends Component {
static propTypes = {
posts: PropTypes.any,
fetchPosts: PropTypes.func,
};
componentDidMount() {
const { fetchPosts } = this.props;
fetchPosts();
}
render() {
const { posts } = this.props;
return (
<div>
<PostForm addPost={this.onSubmit} />
<br />
<div>
{posts.map(post => (
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.body}</p>
</div>
))}
</div>
</div>
);
}
}
export default Post;
Next i have my PostContainer.js
import { connect } from 'react-redux';
import Post from './Post';
import { fetchFromApi } from '../reducers/postReducers';
const mapStateToProps = state => ({
posts: state.posts,
});
const mapDispatchToProps = dispatch => ({
fetchPosts: () => dispatch(fetchFromApi()),
});
export default connect(mapStateToProps, mapDispatchToProps)(Post);
My reducer
import Axios from 'axios';
/* action type */
const FETCH_POSTS = 'FETCH_POSTS';
/* action creator */
export const fetchStarted = payload => ({ payload, type: FETCH_POSTS });
/* thunk */
export const fetchFromApi = () => {
return (dispatch, getState) => {
Axios.get('https://jsonplaceholder.typicode.com/posts?_limit=5').then(res =>
dispatch(fetchStarted(res.data))
);
};
};
/* reducer */
export default function reducer(state = [], action = {}) {
switch (action.type) {
case FETCH_POSTS: {
return {
...state,
data: action.payload,
};
}
default:
return state;
}
}
and my store
import { combineReducers, applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension';
import postReducer from './reducers/postReducers';
const initialState = {
posts: {
data: {},
},
};
const reducers = {
posts: postReducer,
};
Object.keys(initialState).forEach(item => {
if (typeof reducers[item] == 'undefined') {
reducers[item] = (state = null) => state;
}
});
const combinedReducers = combineReducers(reducers);
const store = createStore(
combinedReducers,
initialState,
composeWithDevTools(applyMiddleware(thunk))
);
export default store;
All of that is doing not much. My map method is trying to map empty posts object. And for some reason my fetchPosts is not dispatched. I have reade some old posts here but still can't get this working
Thanks
Edit
this is my app.js file with container
import React from 'react';
import './App.css';
import Post from './components/PostContainer';
import { Provider } from 'react-redux';
import store from './store';
function App() {
return (
<Provider store={store}>
<div className='App'>
<Post />
</div>
</Provider>
);
}
export default App;
I managed to get this working.
Data was not there when my posts array was render. After passing simple if statemante all is working
I'm setting up my app with redux, and i'm new to it. I want to make onClick() event to take item's id but im getting error.
I searched a lot of answers here, but they didn't help me a lot.
Documentation says, that i'm not connecting my action right, but I found no good explanation, only example with toDo, which is not enough for me.
Products.js(where I want my onClick())
import React, { Component } from "react";
import Navbar from "../navbar/Navbar";
import Product from "../lists/Product";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { getItems } from "../../actions/getItems";
import { getDetails } from "../../actions/getDetails";
class Products extends Component {
componentDidMount() {
this.props.getItems();
}
render() {
return (
<div className="container-fluid products">
<Navbar />
<div className="container">
<h1 className="title display-3 text-center pt-2">
<b>Our Products</b>
</h1>
<div className="underline" />
<div className="py-5">
<div className="container">
<div className="row">
{this.props.shopItems.items.map(item => {
return (
<div
onClick={() =>this.props.getDetails(item.id)}
className="col-lg-3 col-md-6 col-sm-6 col-xs-9"
key={item.id}
>
<div className="card-deck">
<Product
name={item.name}
brand={item.brand}
img={item.img}
price={item.price}
/>
</div>
</div>
);
})}
</div>
</div>
</div>
</div>
</div>
);
}
}
Products.propTypes = {
shopItems: PropTypes.object.isRequired,
getDetails:PropTypes.func.isRequired
};
const mapStateToProps = state => ({
shopItems: state.shopItems
});
export default connect(
mapStateToProps,
{ getItems }
)(Products);
getDetails.js
import {SHOW_DETAILS} from './types';
import {data} from '../data/data';
export const getDetails = id => dispatch =>{
const detailProduct = data.find(item => item.id === id)
dispatch({
type:SHOW_DETAILS,
payload:detailProduct
})
}
detailsReducer.js
import { SHOW_DETAILS } from "../actions/types";
const initialState = {
detailProduct: {}
};
export default (state = initialState, action) => {
switch (action.type) {
case SHOW_DETAILS:
return {
detailProduct: action.payload
};
default:
return state;
}
};
index.js(root reducer)
import {combineReducers} from 'redux'
import itemsReducer from './itemsReducer'
import detailsReducer from './detailsReducer';
export default combineReducers({
shopItems:itemsReducer,
detailProduct:detailsReducer
})
Store.js
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import rootReducer from './reducers/index';
const initialState = {};
const middleware = [thunk];
let store = createStore(
rootReducer,
initialState,
compose(
applyMiddleware(...middleware),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
export default store;
I expect:
Connect action getDetails to component Products.js.
Make onClick() to grab needed item's id.
Use find() item by it's id, receive item's info in state detailProduct.
No errors.
I'm working on a little app to learn more about how to use redux. From my interpretations of what is written about redux, you can store and update data on the store. In my app, I have a HTML form with two text inputs that when submitted uses an action creator function to handle submission. The creator function then dispatches the data to a reducer function, which is suppose to store the data into the redux store. When I console.log out the store, there is no data stored in the redux store. Does anyone see where my problem lies or if my interpretation of what redux is suppose to do is wrong?
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import reduxThunk from 'redux-thunk';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import rootReducer from './truth/reducers'
const store = createStore(rootReducer(), {}, applyMiddleware(reduxThunk));
console.log(store.getState());
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
SimpleForm.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { compose } from 'redux'
import { Field, reduxForm } from 'redux-form';
import { fetchName }from '../truth/actions';
class SimpleForm extends Component {
render() {
const { handleSubmit, pristine, reset, submitting, fetchName} = this.props;
return (
<form onSubmit={handleSubmit(fetchName)}>
<br />
<Field name="fname" type="text" component="input" label="First Name" />
<Field name="lname" type="text" component="input" label=" Last Name" />
<div>
<button type="submit" disabled={submitting}> Submit </button>
<button type="button" disabled={pristine || submitting} onClick={reset}> Reset </button>
</div>
</form>
);
}
}
const myReduxForm = reduxForm({
form: "mySimpleForm",
onSubmit: fetchName,
onSubmitSuccess: (result, dispatch) => {
console.log("I am in the onSubmitSuccess func");
console.log('i am after dispatch');
}
})
export default compose(
connect(null, {fetchName} ),
myReduxForm
)(SimpleForm);
actions' index.js file
import { WHOLE_NAME, MY_LIKES} from './types';
import axios from 'axios';
export const fetchName = (values) => async dispatch => {
//const res = axios.post();
console.log("I am in fetchName");
console.log(values);
dispatch({type: WHOLE_NAME, payload: values});
}
nameReducer.js
import { WHOLE_NAME } from '../actions/types';
const name = {
fname: "",
lname: ""
}
export const setNames = (state = name, action) => {
console.log("I am in setnNames")
console.log(action.payload);
let myPayload = {...action.payload};
console.log(myPayload.fname); //logs out correctly
switch (action.type) {
case WHOLE_NAME:
return { ...state, fname: myPayload.fname, lname: myPayload.lname }
default:
return state;
}
}
reducers' index.js file
import { combineReducers } from 'redux';
import { setNames } from './nameReducer';
import { reducer as reduxFormReducer } from 'redux-form';
const rootReducer = () => combineReducers({
setNames,
form: reduxFormReducer
});
export default rootReducer;
const store = createStore(rootReducer(), {}, applyMiddleware(reduxThunk));
console.log(store.getState()); //this is called only once before you even render anything
You can use redux devtools to see what does the store looks like in any particular moment.
https://github.com/zalmoxisus/redux-devtools-extension