Getting undefined result from dispatcher - reactjs

I am trying to get the details of film using redux into the react component
but getting it like undefined , here is my code :
Film Service :
import axios from 'axios';
import config from '../config/config';
export const FilmServices = {
getAllFilms,
searchFilm,
getFilmByID
};
function getFilmByID(apiEndpoint){
return axios.get(config.detailsUrl+apiEndpoint).then((response)=>{
return response;
}).catch((err)=>{
console.log(err);
})
}
Film Action :
import {FilmServices} from '../../services/FilmServices'
export function getFilmByID(idFilm) {
return dispatch => {
FilmServices.getFilmByID(idFilm)
.then((response) => {
if (response) {
dispatch(GET_FILMS_BY_ID(response));
}
})
}
}
function GET_FILMS_BY_ID(response){
return{
type: "GET_FILMS_BY_ID",
payload: response
}
}
Film Reducer :
const initialState = { film: {}}
export function filmreducer(state = initialState, action) {
case 'GET_FILMS_BY_ID':
console.log(action.payload.data)
return{
...state,
film : action.payload.data
};
default:
return state
}
}
And Details Component
import React, {Component} from 'react';
import connect from "react-redux/es/connect/connect";
import {getFilmByID} from "../store/actions/FilmActions";
class Details extends Component {
componentDidMount() {
const {idFilm} = this.props.match.params
const {dispatch } = this.props;
dispatch(getFilmByID(idFilm));
}
constructor(props) {
super(props);
}
render() {
const {film} = this.props.Film;
return (
<React.Fragment>
{/*<h1>{this.idFilm}</h1>*/}
<h1>{film.name}</h1>
</React.Fragment>
);
}
}
const mapStateToProps = (state) =>{
const { Film } = state.filmreducer;
return {
Film
};
}
export default connect(
mapStateToProps
)(Details);
I am getting this error :
TypeError: Cannot read property 'film' of undefined
But when i log my data from filmAction i'm correctly getting the response but not in the component .
Can any one help me please ?

Looks like it's just a situation of cases.
find fixes below
...
render() {
const { film } = this.props;
...
}
}
const mapStateToProps = (state) =>{
const { film } = state.filmreducer;
return {
film
};
}

Related

why is this.props.category returning undefined? Redux

why is my this.props.category returning undefined both in the current version of the code, and also in the code that is commented out?
I followed a youtube video and did everything as instructed i don't understand what the issue might be.
Any help is appreciated! Thank you in advance!
import React, { Component } from 'react'
import "./ProductListPage.css";
import { GET_PRODUCTS } from '../api/index.js'
import { Query } from 'react-apollo'
import { connect } from "react-redux";
import {changeCategory} from "../state/actions/"
export class ProductListPage extends Component {
render() {
{console.log(state.category)}
return (
<div>{this.props.category}</div>
// <Query query={GET_PRODUCTS}>
// {
// ({ data, previousData, loading, error }) => {
// if (loading) return <div>Loading...</div>
// if (error) return <div>Error: {error}</div>
// console.log(this.props.category)
// return (
// <>
// <div>{this.props.category}jj</div>
// </>
// )
// }
// }
// </Query>
)
}
}
const mapStateToProps = (state) => {
return {
category: state.category
};
};
const mapDispatchToProps = (dispatch) => {
return {
changeCategory
}
}
export default connect(mapStateToProps)(ProductListPage)
My state
Did you try:
const mapStateToProps = (state) => {
return {
category: state.categoryReducer, // change here
};
};
if it does not work, check the key of category reducer that has been register when combine all reducer and put to store

React API this.props.message.map is not a function

I use the API to get Quotes, but I get an Unhandled Rejection error "(TypeError): this.props.message.map is not a function" https://ibb.co/dWqhjXK, I used debugger checked props saw that I get answers https://ibb.co/wM3mLb9 what then could be the reason? why am i getting this error? here is my code
Message.jsx
import React from 'react';
export class Message extends React.Component {
render() {
const list = this.props.message.map((item, index) => {
return <div key={index}>
<p>{item.content}</p>
</div>
});
return (
<div>
<p>{list}</p>
</div>
);
}
}
MessageContainer.js
import React from 'react';
import {connect} from "react-redux";
import {Message} from "./Message";
import {getMessageThunk} from "../../redux/message-reducer";
class MessageContainer extends React.Component {
componentDidMount() {
this.props.getMessageThunk();
}
render() {
return <Message {...this.props} />
}
}
const mapStateToProps = (state) => ({
message: state.message.users
})
export default connect(mapStateToProps, {getMessageThunk})(MessageContainer);
message-reducer.js
import {messageAPI} from "../Api/Api";
const MESSAGE = 'MESSAGE';
let initialState = {
users: [],
};
export const messageReducer = (state = initialState, action) => {
switch (action.type) {
case MESSAGE: {
return {...state, users: action.users}
}
default:
return state;
}
}
export const messageCreator = (users) => {
return {
type: MESSAGE, users
}
};
export const getMessageThunk = (users) => (dispatch) => {
messageAPI.getMessageAPI(users).then(response => {
dispatch(messageCreator(response.data));
})
}
Api.js
import * as axios from "axios";
const instance = axios.create({
withCredentials: true,
url: 'https://quotes15.p.rapidapi.com/quotes/random/',
headers: {
'x-rapidapi-key': 'bf490d72a0msh3bf159a87e0c27fp107a51jsn062ca1b9b00e',
'x-rapidapi-host': 'quotes15.p.rapidapi.com'
}
});
export const messageAPI = {
getMessageAPI() {
return instance.get(`https://quotes15.p.rapidapi.com/quotes/random/`)
},
};
Your message is not an array but an object. You do not have anything to iterate over there you could either simply return this.props.message.content but this is not a list.
const item = <p>{this.props.message.content}</p>

Redux State null in render method, even after redux state is updated correctly

I am in learning phase of react, and creating small application which fetches user wishlist from firebase table and updated redux store and I am trying to access that redux store in render method but when i console.log this.props.wishlist in render method its shows null. Redux state is updated correctly. Checked with redx dev tool.
redux state screenshot
Action creator which gets wishlist data from firebase API
export const fetchWishlist = (email)=> {
return dispatch => {
dispatch(fetchWishlistStart());
let rawMovieId=[];
let uniqueMovieIdList = [];
const queryParams ='?orderBy="email"&equalTo="'+email+'"';
axios.get('https://movie-project-6fc34.firebaseio.com/wishlist.json'+queryParams)
.then (response=>{
for(let key in response.data){
rawMovieId.push(response.data[key].movieId)
}
uniqueMovieIdList = [ ...new Set(rawMovieId) ];
dispatch(fetchMovieDetailsForWishlist(uniqueMovieIdList))
})
.catch(error=> {
console.log(error);
})
}
}
export const setMovieDetailsForWishlist = (movieDetailsList)=> {
return {
type:actionType.SET_MOVIEDETAILS_WISHLIST,
movieDetailsList:movieDetailsList
}
}
export const fetchMovieDetailsForWishlist = (movieList) => {
return dispatch => {
dispatch(fetchWishlistSuccess());
let updatedMovieList = []
movieList.map((currItem)=>{
let final_api_url = api_url+movieDetails_api_end_point+currItem+api_key+'&language='+language
axios.get(final_api_url)
.then(response=>{
updatedMovieList.push({
title:response.data.title,
movieId:response.data.id,
poster:response.data.poster_path
})
})
.catch(error=>{
console.log(JSON.stringify(error));
})
})
dispatch(setMovieDetailsForWishlist(updatedMovieList));
}
}
WhislistReducer --
import * as actionType from '../actions/actionType.js'
const intialState = {
wishList:null,
showLoader:false
}
const wishListReducer = (state=intialState, action) => {
switch (action.type) {
case actionType.FETCH_WISHLIST_START:
return {
...state,
showLoader:true
}
case actionType.FETCH_WISHLIST_SUCCESS:
return {
...state,
showLoader:false
}
case actionType.SET_MOVIEDETAILS_WISHLIST:
return {
...state,
showLoader:false,
wishList:action.movieDetailsList
}
default:
return state
}
}
export default wishListReducer;
wishlist component
import React, { Component } from 'react';
import {connect} from 'react-redux';
import {withRouter} from 'react-router-dom';
import * as action from '../store/actions/index'
export class Wishlist extends Component {
componentDidMount() {
this.props.fetchWishlist(window.localStorage.getItem('email'));
render() {
let wishListPageContent = '<div> Loading........</div>'
let userWishlistDetails = this.props.wishlist
console.log(userWishlistDetails);
if (!this.props.showLoader) {
wishListPageContent = (
<div> wishlist component</div>
)
}
return (
<div>
{wishListPageContent}
</div>
);
}
}
const mapStateToProps = state => {
return {
userEmail:state.authState.userEmail,
wishlist:state.wishlistState.wishList,
isAuthSuccess:state.authState.isAuthSuccess,
showLoader:state.wishlistState.showLoader
}
}
const mapDispatchToProps = dispatch => {
return {
fetchWishlist:(email)=>dispatch(action.fetchWishlist(email)),
fetchMovieDetailsForWishlist:(movieList)=>dispatch(action.fetchMovieDetailsForWishlist(movieList))
}
}
export default withRouter(connect(mapStateToProps,mapDispatchToProps)(Wishlist));

Component is not showing

Component is not showing. I don't get any error messages. I am trying to fetch data from a url and build a simple list on PollList from that data. I can console.log(polls) from the action and it works but it just doesn't build the list
Here is the code.
pollsactions.js
import { GET_POLLS, POLLS_LOADING } from './types';
export const getPolls = () => dispatch => {
return fetch(URL)
.then(res => res.json())
.then(polls => {
dispatch({
type: GET_POLLS,
payload: polls
})
})
}
pollsreducers.js
import {
GET_POLLS,
POLLS_LOADING
} from '../actions/types';
const pollReducer = (state = [], { type, payload }) => {
switch (type) {
case GET_POLLS:
return payload
default:
return state
}
}
export default pollReducer;
PollList.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { getPolls } from '../redux/actions/pollsActions';
class PollList extends Component {
componentDidMount() {
this.props.getPolls();
}
render() {
const { polls } = this.props.polls
return (
<div>
{
polls && polls.map((poll) => (
<div key={poll.id}>
{(poll.type)}
</div>
))
}
</div>
)
}
}
const mapStateToProps = state => ({
polls: state.polls
});
export default connect(
mapStateToProps,
{ getPolls }
)(PollList);
You are destructuring polls incorrectly. polls is on this.props based on your mapStateToProps(), not on this.props.polls. Try changing:
const { polls } = this.props.polls;
to:
const { polls } = this.props;
Otherwise, without destructuring, it would look like:
const polls = this.props.polls;
Hopefully that helps!

React component doesn't update after updating state with redux action

/keywordsActions
import { UPDATE_KEYWORDS } from "./actionTypes";
import queryString from "query-string";
const keywordsArrayFromUrl = () => {
const query = queryString.parse(window.location.search);
if (query.keywords) {
const removeDuplicate = new Set(query.keywords.split(" "));
return Array.from(removeDuplicate);
}
return [];
};
export function updateKeywords() {
return async dispatch => {
dispatch({
type: UPDATE_KEYWORDS,
payload: await keywordsArrayFromUrl()
});
};
}
/keywordReducer
import { UPDATE_KEYWORDS } from "../actions/actionTypes";
export default function(state = [], action) {
switch (action.type) {
case UPDATE_KEYWORDS:
return action.payload;
default:
return state;
}
}
/SearchBar -- React Component
import React, { Component } from "react";
import { withRouter } from "react-router-dom";
//Redux
import { connect } from "react-redux";
import { updateKeywords } from "../store/actions/KeywordsAction";
class Searchbar extends Component {
constructor(props) {
super(props);
this.state = {
keywords : this.props.keywords
keywordsString: this.props.keywords.join(" ")
};
}
componentDidMount() {
this.props.updateKeywords();
console.log(this.props)
setTimeout(() => console.log(this.props), 10);
}
_handleChange = e => {
this.setState({ keywordsString: e.target.value });
};
_handleSearch = value => {
this.setState({ keywordsString: value });
this.props.history.push(`/search?keywords=${value}`);
};
render() {
return (
<Search
className="Searchbar"
placeholder="Cauta prin iBac..."
value={this.state.keywordsString}
onChange={this._handleChange}
onSearch={this._handleSearch}
/>
);
}
}
const mapStateToProps = state => {
return {
keywords: state.keywords
};
};
export default connect(
mapStateToProps,
{ updateKeywords }
)(withRouter(Searchbar));
I want to save the keywords from the Url to the store and then pass it to the Search bar state.
But i dont understand this :
componentDidMount() {
this.props.updateKeywords();
console.log(this.props); // this.props.keywords is empty
setTimeout(() => console.log(this.props), 10); // After 10 ms this.props.keywords is no empty
}
After 10 ms the props of Searchbar gets updated but the component doesn't render again.
Sorry for my question, I am really new to React / Redux. Please let me know what I am doing wrong. Thank you all!
Update :
componentDidMount() {
this.props.updateKeywords();
setTimeout(() => {
this.setState({
keywordsString: this.props.keywords.join(" ")
});
}, 0);
}
This code is also working... but this other is not working
componentDidMount() {
this.props.updateKeywords();
this.setState({
keywordsString: this.props.keywords.join(" ")
});
}
The reason is that componentDidMount is only called once on mount. What you're looking for is either componentShouldUpdate or componentDidUpdate or the render function, all of which are called when your component receives the updated state from redux. You can read here for more information on what these functions do.
https://reactjs.org/docs/react-component.html#updating

Resources