Hello i've an issue where my redux state not causing a re-render when i'm trying to use a selector. I'm pretty new to react-redux and typescript. I've been trying to google this and most internet threads say it's because you need to create a new object and return that to let redux know that state has changed. Which im already doing. But my object is not re-rendering, the state IS updated but not causing a rerender.
What am i doing wrong?
My Redux reducer
import { Computer, GraphicsCard } from "../../interfaces";
const initialState: Computer = {
graphicsCard: null,
}
interface SelectGraphicsCardAction {
type: "SELECT_GRAPHICSCARD";
payload: GraphicsCard;
}
interface UnselectGraphicsCardAction {
type: "UNSELECT_GRAPHICSCARD";
}
export type Action = SelectGraphicsCardAction | UnselectGraphicsCardAction
export const computerReducer = (state = initialState, action: Action) => {
switch(action.type){
case "SELECT_GRAPHICSCARD": {
const { payload } = action;
console.log(state, payload)
const newState = {
...state,
graphicsCard: {
...state.graphicsCard,
...payload
}
}
//This evaluates to false
console.log(state === newState)
return newState
}
case "UNSELECT_GRAPHICSCARD": {
return {
...state,
graphicsCard: null
}
}
default:
return state;
}
}
My Redux Store
import { configureStore } from '@reduxjs/toolkit'
import { computerReducer } from './reducers/ComputerReducer'
// ...
export const store = configureStore({
reducer: {
computer: computerReducer
},
})
Im selecting/using the state here.
function SelectedComputer() {
const computer = useSelector((state: Computer) => state);
const dispatch = useDispatch();
const { graphicsCard } = computer;
//Logging correct state
console.log(computer)
return (
<div className="fixed top-10 right-4 bg-white rounded-t-lg">
<p className="text-center font-bold border-b-1 border-b-black bg-gray-100 rounded-t-lg shadow-md">
Selected Parts
</p>
<div className="flex flex-row">
<CpuFill className="m-1" />
{graphicsCard ? (
//Not rendering this when updating state.
<p>{graphicsCard.name}</p>
) : (
<p>No Graphicscard selected!</p>
)}
<Trash className="flex justify-center"/>
</div>
EDIT: Here is a snippet where am using dispatch to update the state.
import React, { FC } from "react";
import { Button, Card } from "react-bootstrap";
import { useDispatch } from "react-redux";
import { Component, ComputerComponent } from "../interfaces";
import { Action } from "../redux/reducers/ComputerReducer";
interface ComponentCard {
component: Component;
buttonText: string;
type: string;
}
interface DomainImage {
[key: string]: string;
}
const ComponentCard: FC<ComponentCard> = ({ component, buttonText, type }) => {
const dispatch = useDispatch();
const imageMap: DomainImage = {
"inet.se": "https://cdn.inet.se/gfx/ext/226/brand-assets/inet-logo2.jpg",
"komplett.se":
"https://cached-images.bonnier.news/gcs/di-bilder-prod/mly/fcb28d10-158c-485b-814c-b461baa0e188.jpeg",
"webhallen.se":
"https://static.wikia.nocookie.net/logopedia/images/6/65/Webhallen_2021.svg/revision/latest?cb=20220420201224",
};
return (
<Card className="flex flex-row items-center w-50 shadow-md mt-2 mb-2">
<div className="flex justify-center items-center mr-3">
<img className="h-36 w-40 p-2" src={component.imgUrl} />
</div>
<div className="flex-1 text-left">
<h4 className="text-base">{component.name}</h4>
<p>
<span>
ArtNr: {component.articleNumber}, Manufacturer:{" "}
{component.manufacturer}
</span>
</p>
<h4 className="absolute right-36 top-10">
<span>{component.price} :-</span>
</h4>
</div>
<Button
color=""
className="absolute right-5 h-10 w-20"
onClick={() => dispatch({ type, payload: component })}
>
{buttonText}
</Button>
<a href={component.url} target="_blank" className="absolute right-5 bottom-0">
<img
className="w-15 h-10"
src={imageMap[component.domainName]}
alt={component.name}
/>
</a>
</Card>
);
};
CodePudding user response:
For what it's worth, you are using an extremely outdated (pre-2019) style of Redux here that will end up being about 4x the code you would write with modern Redux - especially in combination with TypeScript.
I would highly recommend you to follow the official Redux tutorial and the TypeScript QuickStart that will show you all the additional types you have to set up (it's a lot less than what you have right now).
The source of your problem is likely an accidental state modification, which can also happen outside of reducers in legacy Redux - in modern Redux you would get an error immediately at the point where you make the mutation - saving you hours of debugging. So I'd really recommend you just switch over and you'll probably be rid of this bug.