Reputation: 1122
I would like to know how redux implementation in functional component different from class component.
Because I got a working example and not working example.
The working example is the class component. When I use class component and use props.fetchSomething
Its always works.
here is the class component.
import React, { Component } from "react";
class Posts extends Component {
componentDidMount() {
this.props.fetchPosts();
}
render() {
let postItems = this.props.posts.map((post) => (
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.body}</p>
</div>
));
return <div>{postItems}</div>;
}
}
Now I will show you the not working version of function component.
import React, { useEffect } from "react";
const Posts = ({ fetchPosts, posts }) => {
useEffect(() => {
fetchPosts();
}, []);
let items = posts.map((post) => {
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.body}</p>
</div>;
});
return <div>{items}</div>;
};
As you can see, FROM MY UNDERSTANDING
these 2 works the same, Because i fetch the data at mounting state and map the store data.
Here my rest of the code. which are redux operations. I used these below codes for both class and function component. The thing is, only the class component show the list of data. The function component always return an empty array.
WHY IS THAT
Posts.propTypes = {
fetchPosts: PropTypes.func.isRequired,
posts: PropTypes.array.isRequired,
newPost: PropTypes.object,
};
const mapStateToProps = (state) => ({
// coming from root reducer
posts: state.posts.itemsArray,
newPost: state.posts.item,
});
export default connect(mapStateToProps, { fetchPosts })(Posts);
Upvotes: 0
Views: 94
Reputation: 39290
Items is not assigned to anything because the callback function passed to map doesn't return anything:
useEffect(() => {
fetchPosts();
//you should really try using create-react app, then
// you'd see the missing dependency when compiling
// When you also set up vs code you'd see it when you
// open the file in the editor
}, [fetchPosts]);
//in VS code you would have a linter warning:
// Expected to return a value in arrow function.
// also defined items as const
const items = posts.map((post) => (//replaced { with (
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.body}</p>
</div>//removed ;
)/**replaced } with ) */);
If you use {...}
after the arrow of an arrow function then ...
is the body of the function and you have to return something from this body:
let items = posts.map((post) => {
return (//have to return jsx
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.body}</p>
</div>
); //removed ;
});
You can also have an arrow function that has no body, then whatever comes after the arrow is the return value. For example: const add = (a,b)=>a+b
.
If you have a bodyless arrow function that returns an object it gets confusing because an object and a function body have the same syntax {}
so to return an object you can do ({})
, here is an example: const add = (a,b)=>({sumAB:a+b})
. With jsx the (<jsx />)
are optional so const hello = () => <div>hello</div>;
and const hello = () => (<div>hello</div>);
are both valid. When multi line jsx is returned a formatter such as prettier will usually format it with (<jsx />)
like so:
const hello = () => (
<div>
<div>hello</div>
</div>
);
Upvotes: 1