I have this class component that returns state populated perfectly using Redux store:
class TopRatedComponent extends Component {
componentDidMount() {
this.props.fetchTopRatedMovies();
}
render() {
const IMG_API_ROOT_LINK = 'https://image.tmdb.org/t/p/w500';
const { topRatedMovies, loading, error } = this.props;
return (
<div>
{loading && <div>LOADING...</div>}
{error && <div>{error}</div>}
<Container className="p-4" onScroll={this.onScroll}>
<div className="text-center">
{
topRatedMovies.results && topRatedMovies.results.map(topRated => (
<p>{topRated.title}</p>
))
}
</div>
</Container>
</div>
);
}
}
const mapStateToProps = state => {
const { topRatedMovies, loading, error } = state.topRatedMovies;
return {
topRatedMovies,
loading,
error
};
};
export default connect(
mapStateToProps,
{
fetchTopRatedMovies
}
)(TopRatedComponent);
However, when I switch the above class component into a functional component below so I can use ReactJS hooks with my code, but the state is always empty.
const TopRatedComponent = () => {
const [count, setCount] = useState(0);
const [topRated, settopRated] = useState([]);
useEffect(() => {
settopRated(this.props.fetchTopRatedMovies)
}, [this.props.fetchTopRatedMovies])
const allState = useSelector((state) => state)
console.log('CHOF: ' + JSON.stringify(allState));
return (
<div>
WOOOOOOOW....
</div>
)
};
You haven't correctly transformed your class-based component into equivalent functional component.
Following are the problems in your functional component:
In class component, you receive the fetchTopRatedMovies
action creator as a prop and you dispatch it from the componentDidMount
lifecycle method. In functional component, you are not dispatching it.
To dispatch the action in functional components, use useDispatch() hook and use useEffect
hook to dispatch this action after component has mounted.
import React, { useEffect } from "react";
import { useDispatch } from "react-redux";
const TopRatedComponent = () => {
...
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchTopRatedMovies());
}, []);
...
};
In class components, you access props
object using this
but in functional components, props
object is passed as an argument. So, you can directly access it using the parameter name you use for the props
object
const TopRatedComponent = (props) => {
console.log(props);
// code
};
Data that your component receives as props from the redux store using mapStateToProps
function and connect
higher order component, can be accessed using useSelector hook in functional components.
import { useSelector } from "react-redux";
const TopRatedComponent = () => {
const {
topRatedMovies,
loading,
error
} = useSelector(state => state.topRatedMovies);
// code
};
Note: You can also use connect
higher-order component and mapStateToProps
to connect your functional component with the redux store.
For details of how to use hooks with react-redux
, see: react-redux - Hooks