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')
);
Related
I have the following problem: Using the code below I get the error:
this.props.posts is undefined
As I am following the tutorial https://codeburst.io/redux-a-crud-example-abb834d763c9 an I typed everything correct I am totally confused already at the beginning of my React career. Could you please help me?
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Post from './Post';
class AllPost extends Component {
render() {
return (
<div>
<h1>All Posts</h1>
{this.props.posts.map((post) => <Post key={post.id} post={post} />)}
</div>
);
}
}
const mapStateToProps = (state) => {
return {
posts: state,
}
}
export default connect(mapStateToProps)(AllPost);
Thanks a lot for your efforts!
The following is the postReducer:
const postReducer = (state = [], action) => {
switch(action.type) {
case 'ADD_POST':
return state.concat([action.data]);
default:
return state;
}
}
export default postReducer;
And here the index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import postReducer from './reducers/postReducer';
const store = createStore(postReducer);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>, document.getElementById('root'));
You need to declare an initial state. So your this.props.posts won't be undefined.
const initialState = {
posts: []
}
const postReducer = (state = initialState, action) => {
switch(action.type) {
case 'ADD_POST':
return { ...state, posts: [...state.posts, action.data]}
default:
return state;
}
}
export default postReducer;
The second error is located inside your mapStateToProps method. You need to access to posts redux state key. posts: state.posts like I did below
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Post from './Post';
class AllPost extends Component {
render() {
return (
<div>
<h1>All Posts</h1>
{this.props.posts.map((post) => <Post key={post.id} post={post} />)}
</div>
);
}
}
const mapStateToProps = (state) => {
return {
posts: state.posts, // you need to access to posts key
}
}
export default connect(mapStateToProps)(AllPost);
I am trying to build a simple counter using React and Redux but I am stuck with this error. The error comes up on line 23, that is const store=createStore(reducer). The React version I am using is 16.8.6.
import React, { Component } from 'react';
import {render} from 'react-dom';
import {createStore} from 'react';
import {connect,Provider} from 'react-redux';
import './styles.scss';
const InitialState = {
count: 0,
};
const IncrementValue = () => ({
type: 'INCREMENT',
});
const reducer = (state = InitialState, action) => {
if (action.type === 'INCREMENT') {
return {
count: state.count + 1,
};
}
return state;
};
const store = createStore(reducer);
class Counter extends Component {
render() {
const { count, increment } = this.props;
console.log({ count, increment });
return (
<main className="Counter">
<p className="count">0</p>
<section className="controls">
<button>Increment</button>
<button>Decrement</button>
<button>Reset</button>
</section>
</main>
);
}
}
const mapStatetoProps = state => {
return state;
};
const mapDispatchToProps = dispatch => {
return {
increment() {
dispatch(IncrementValue());
},
};
};
const CounterContainer=connect(mapStatetoProps, mapDispatchToProps)(Counter);
render(
<Provider store={store}>
<CounterContainer/>
</Provider>,
document.getElementById('root'),
);
createStore is a function of Redux, not React.
Change import to
import { createStore } from 'redux';
I don't know how to load the data of the fetchLatestAnime action in the react app.js file.
My mission is to show the endpoint data that I am doing fetch.
I have already implemented the part of the reducers and action, which you can see in the part below. The only thing I need is to learn how to display the data.
App.js
import React from 'react';
import './App.css';
function App() {
return (
<div className="App">
</div>
);
}
export default App;
actions/types.js
export const FETCHING_ANIME_REQUEST = 'FETCHING_ANIME_REQUEST';
export const FETCHING_ANIME_SUCCESS = 'FETCHING_ANIME_SUCCESS';
export const FETCHING_ANIME_FAILURE = 'FETCHING_ANIME_FAILURE';
actions/animesActions.js
import{
FETCHING_ANIME_FAILURE,
FETCHING_ANIME_REQUEST,
FETCHING_ANIME_SUCCESS
} from './types';
import axios from 'axios';
export const fetchingAnimeRequest = () => ({
type: FETCHING_ANIME_REQUEST
});
export const fetchingAnimeSuccess = (json) => ({
type: FETCHING_ANIME_SUCCESS,
payload: json
});
export const fetchingAnimeFailure = (error) => ({
type: FETCHING_ANIME_FAILURE,
payload: error
});
export const fetchLatestAnime = () =>{
return async dispatch =>{
dispatch(fetchingAnimeRequest());
try{
let res = await axios.get('https://animeflv.chrismichael.now.sh/api/v1/latestAnimeAdded');
let json = await res.data;
dispatch(fetchingAnimeSuccess(json));
}catch(error){
dispatch(fetchingAnimeFailure(error));
}
};
};
reducers/latestAnimeReducers.js
import {
FETCHING_ANIME_FAILURE,
FETCHING_ANIME_REQUEST,
FETCHING_ANIME_SUCCESS
} from '../actions/types';
const initialState = {
isFetching: false,
errorMessage: '',
latestAnime: []
};
const latestAnimeReducer = (state = initialState , action) =>{
switch (action.type){
case FETCHING_ANIME_REQUEST:
return{
...state,
isFetching: true,
}
case FETCHING_ANIME_FAILURE:
return{
...state,
isFetching: false,
errorMessage: action.payload
}
case FETCHING_ANIME_SUCCESS:
return{
...state,
isFetching: false,
latestAnime: action.payload
}
default:
return state;
}
};
export default latestAnimeReducer;
reducers/index.js
import latestAnimeReducers from './latestAnimeReducers'
import {combineReducers} from 'redux';
const reducers = combineReducers({
latestAnimeReducers
});
export default reducers;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import resolvers from './redux/reducers/index';
import {createStore , applyMiddleware} from 'redux';
import {Provider} from 'react-redux';
import thunk from 'redux-thunk';
const REDUX_DEV_TOOLS = window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
const store = createStoreWithMiddleware(resolvers , REDUX_DEV_TOOLS)
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
serviceWorker.unregister();
Ideally, this is how your app.js should look like. I created a working codesandbox for you here. Your initial latestAnime state was an empty array but the action payload you set to it is an object, so remember to pass payload.anime like i have done in the sandbox.
import React, { useEffect } from "react";
import { connect } from "react-redux";
import { fetchLatestAnime } from "./redux/actions/animesActions";
const App = props => {
const { fetchLatestAnime, isFetching, latestAnime, errorMessage } = props;
useEffect(() => {
fetchLatestAnime();
}, [fetchLatestAnime]);
console.log(props);
if (isFetching) {
return <p>Loading</p>;
}
if (!isFetching && latestAnime.length === 0) {
return <p>No animes to show</p>;
}
if (!isFetching && errorMessage.length > 0) {
return <p>{errorMessage}</p>;
}
return (
<div>
{latestAnime.map((anime, index) => {
return <p key={index}>{anime.title}</p>;
})}
</div>
);
};
const mapState = state => {
return {
isFetching: state.latestAnimeReducers.isFetching,
latestAnime: state.latestAnimeReducers.latestAnime,
errorMessage: state.latestAnimeReducers.errorMessage
};
};
const mapDispatch = dispatch => {
return {
fetchLatestAnime: () => dispatch(fetchLatestAnime())
};
};
export default connect(
mapState,
mapDispatch
)(App);
The app is just supposed to display 'Hello' and when you click on it, switch to 'Goodbye', but it won't render 'Hello'. I've set default state, connected everything, etc. but I can't figure out what I'm missing.
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { connect } from 'react-redux';
import "./styles.css";
const switcheroo = () => {
return {
type: 'SWITCH'
};
};
const switchReducer = (state = {value: 'Hello'}, action) => {
switch (action.type) {
case 'SWITCH':
return { ...state, value: 'Goodbye' };
default:
return state;
}
}
class ClickMachine extends React.Component {
render() {
const { value, switcheroo } = this.props;
return(
<div >
<p onClick={switcheroo}>{value}</p>
</div>
)
}
};
const mapStateToProps = (state) => ({
value: state.value,
});
const mapDispatchToProps = (dispatch) => ({
switcheroo: () => dispatch(switcheroo()),
});
connect(mapStateToProps, mapDispatchToProps)(ClickMachine);
const store = createStore(switchReducer);
class AppWrapper extends React.Component {
render() {
return (
<Provider store={store}>
<ClickMachine />
</Provider>
);
};
};
const rootElement = document.getElementById("root");
render(<AppWrapper />, rootElement);
My CodeSandbox is here: https://codesandbox.io/s/k29r3928z7 and I have the following dependencies:
react
react-dom
react-redux
redux
Its because you've not assigned the connect function to a component, without which redux won't be associated with the ClickMachine Component
just change this line, it will work
ClickMachine = connect(mapStateToProps, mapDispatchToProps)(ClickMachine);
Sandbox link https://codesandbox.io/s/4x2pr03489
Im newbie at Redux and Redux, so im trying get a simple todo list.
I've got array in the store. Its okay with adding, but when im deleting item see this:
TypeError: Cannot read property 'map' of undefined
at
var items =this.props.tasks.map((item,i) => (this.props.deleteTask(item)} />));
in ListTODO.js
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducer from './reducer';
const store = createStore(reducer);
ReactDOM.render(
<Provider store={store}>
<App className="container" />
</Provider>,
document.getElementById('root'));
registerServiceWorker();
App.js
import React, { Component } from 'react';
import InputTask from './InputTask';
import ListTODO from './ListTODO';
import { connect } from 'react-redux';
class App extends Component {
render() {
return (<div>
<strong>TODO LIST</strong>
<InputTask addTask={this.props.addTask} /><br />
<ListTODO tasks={this.props.store} deleteTask={this.props.deleteTask} />
</div>);
}
}
const mapStateToProps = state => {
return {
store: state
}
}
const mapDispatchToProps = dispatch => {
return {
addTask: (task) => {
dispatch({ type: 'UPDATE_LIST', payload: task })
},
deleteTask: (task) => {
dispatch({ type: 'DELETE_TASK', payload: task })
}
}
}
export default connect(
mapStateToProps,
mapDispatchToProps)
(App);
reducer.js
const initialState = ["task1", "task2"];
export default function todoList(state = initialState, action) {
switch (action.type) {
case 'UPDATE_LIST':
return [
...state,
action.payload
];
case 'DELETE_TASK':
console.log("DELETING", (action.payload))
return
state.filter(element => element !== action.payload);
default: return state;
}
}
ListTODO.js
import React, { Component } from 'react';
import TodoItem from './TodoItem';
import { connect } from 'react-redux';
class ListTODO extends Component {
constructor() {
super();
}
render() {
console.log("LIST TODO:"+ this.props.tasks);
var items =this.props.tasks.map((item,i) => (<TodoItem item={item} key={i} deleteTask={(item)=>this.props.deleteTask(item)} />));
return (
<ul>
{items}
</ul>
);
}
}
export default ListTODO;