Reputation: 3125
as I was implementing Redux in my Gatsby project, I saw that my component doesn't re-render when the component's state changes (and yes, I was treating the state as immutable).
So I used Redux's Conuter example, and copied its code into my Gatsby project. And the problem re-occurred, the component fails to re-render when the state changes (using one of Redux's examples!).
Only by using this.forceUpdate()
, were I able to get the component re-render on state changes, and when I removed this line, it stopped re-rendering on state changes.
This is the Gatsby page I've created and the Redux's code I've copied into:
import React, { Component } from 'react'
import { createStore } from 'redux'
class Counter extends Component {
constructor(props) {
super(props);
}
render() {
console.log("render - start",JSON.stringify(store.getState(),null,2))
const { value, onIncrement, onDecrement } = this.props
return (
<p>
Clicked: {value} times
{' '}
<button onClick={onIncrement}>
+
</button>
{' '}
<button onClick={onDecrement}>
-
</button>
</p>
)
}
}
const counter = (state = 0, action) => {
console.log("reducer - start: ",state, JSON.stringify(action,null,2))
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
const store = createStore(counter)
class TestPage extends React.Component {
render(){
return (
<Counter
value={store.getState()}
onIncrement={() => {
store.dispatch({ type: 'INCREMENT' })
// this.forceUpdate()
}}
onDecrement={() => store.dispatch({ type: 'DECREMENT' })}
/>)
}
}
export default TestPage
Upvotes: 1
Views: 462
Reputation: 17858
Did you correctly store.subsribe() ?
I made work it work like this.
index.js
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { store } from "./store";
import Counter from "./Counter";
class App extends Component {
render() {
return (
<Counter
value={store.getState()}
onIncrement={() => {
store.dispatch({ type: "INCREMENT" });
}}
onDecrement={() => store.dispatch({ type: "DECREMENT" })}
/>
);
}
}
const rootElement = document.getElementById("root");
const render = () => ReactDOM.render(<App />, rootElement);
render();
store.subscribe(render);
store.js
import { createStore } from "redux";
const counter = (state = 0, action) => {
switch (action.type) {
case "INCREMENT":
return state + 1;
case "DECREMENT":
return state - 1;
default:
return state;
}
};
export const store = createStore(counter);
Counter.js
import React, { Component } from 'react'
class Counter extends Component {
render() {
const { value, onIncrement, onDecrement } = this.props
return (
<p>
Value: {value}
{' '}
<button onClick={onIncrement}>
+
</button>
{' '}
<button onClick={onDecrement}>
-
</button>
</p>
)
}
}
export default Counter;
A sample codesandbox: https://codesandbox.io/s/redux-counter-2oftu
By the way using redux in react like this not makes much sense, we generally use react-redux package. You should definitely use react-redux package, after learning redux fundementals.
Upvotes: 2