Technologies:
Tolerim
23 days ago
How can I prevent React-Redux-Reducer from saving the same array element from the API in the redux state when the user clicks?
const INIT_STATE = {
movies: [],
};
export const moviereducer = (state = INIT_STATE, action) => {
switch (action.type) {
case "ADD_MOVIE":
return {
movies: [action.payload],
};
default:
return state;
}
};
const Hero = () => {
const [data, setData] = useState([]);
const Dispatch = useDispatch();
const fetchData = () => {
return axios
.get("https://api.tvmaze.com/search/shows?q=all")
.then((response) => setData(response.data));
};
useEffect(() => {
fetchData();
}, []);
const handleClick = (ele) => {
Dispatch(ADD_MOVIE(ele));
};
return (
<div className="heroWrap">
<div className="cardWrap">
{data &&
data.map((ele, id) => {
return (
<Card key={id} style={{ width: "18rem" }}>
<Card.Img variant="top" src={ele.show.image.medium} />
<Card.Body>
<Card.Title>{ele.show.name}</Card.Title>
<Card.Text>Genres: {ele.show.genres + ","}</Card.Text>
<Button onClick={() => handleClick(ele)} variant="primary">
<Link className="text-white" to="/detail">
Read More
</Link>
</Button>
</Card.Body>
</Card>
);
})}
</div>
</div>
);
};
Answers(2)
Vogi
22 days ago
Verified Answer
It seems that you are trying to store data obtained from an API in a Redux state. The code you have provided seems to be correct. However, it is only storing the last element of the array in your Redux state. This is because you are overwriting the previous state with the new one every time you dispatch the action.
To fix this issue, you can use the spread operator to copy the previous state and add the new data to it. Here's how you can modify your reducer code:
const INIT_STATE = {
movies: [],
};
export const moviereducer = (state = INIT_STATE, action) => {
switch (action.type) {
case "ADD_MOVIE":
return {
movies: [...state.movies, action.payload],
};
default:
return state;
}
};
This will add the new data to your existing state instead of overwriting it.
Regarding your second issue of not being able to render the image that you have stored in your Redux state, it seems that you are trying to access the image using the wrong key. In your component code, you are trying to access ele.show.image.medium, but in your Redux state, the key is image. You can modify your component code as follows:
<Card.Img variant="top" src={ele.image} />
This should render the image correctly.
I hope this helps! Let me know if you have any further questions.Sources
Storing Data From API with Redux in React Native AppsHow do I access store state in React Redux? - Stack OverflowQuick Guide for Fetching API Data Using React Redux and Hooks ... - Mediumreactjs - Retrieve data from API using Redux - Stack OverflowHow to fetch data through api in redux? - Stack OverflowTolerim
23 days ago
The reason you are only storing the same data in your redux state no matter which button you click on is because you are replacing the entire movies array with the new movie each time you dispatch the "ADD_MOVIE" action. Instead, you need to add the new movie to the existing array.
Change your case "ADD_MOVIE" block in your reducer to:
return {
movies: [...state.movies, action.payload],
};
This will spread the existing movies array and add the new movie as a new element.
Regarding your new problem of not being able to render the image that you have stored in your redux state, it seems like the issue might be with the way you are trying to access it. It looks like you are trying to access the image using props.movie.show.image.medium, but based on your state structure, the correct way to access the image would be props.movie.image.medium. Try changing this and see if it works: