I've been trying to dispatch a function that will call an async parse cloud function. It worked well in my other projects when i used them in functions. But this is the first time i'm using them in a component and when i call the dispatch from map dispatch to props, I get this error. Please help me out.
ProfileHeader.js
import React, { Component } from 'react';
import Cover_Image from './Cover_Image.jpg';
import Profile_Pic from './Profile_Pic.svg';
import './ProfileHeader.css';
import { connect } from 'react-redux';
import { fetchUserProfile } from '../../Redux/UserProfile-Redux/UserProfileActionMethods';
class ProfileHeader extends Component {
componentDidMount() {
this.props.fetchUserProfile()
}
render() {
return (
<div className="profile-header-layout"></div>
)
}
}
const mapStatetoProps = (state) => {
return {
profile: state.UserProfile
}
}
const mapDispatchtoProps = (dispatch) => {
return {
fetchUserProfile: () => { dispatch(fetchUserProfile()) }, dispatch,
}
}
export default connect(mapDispatchtoProps, mapStatetoProps)(ProfileHeader)
The action Method:
import Parse from 'parse/dist/parse.min.js';
import { FETCH_USERPROFILE_FAILURE, FETCH_USERPROFILE_REQUEST, FETCH_USERPROFILE_SUCCESS } from './UserProfileActions';
const params = { username: "prvnngrj" }
export const fetchUserProfileRequest = () => {
return {
type: FETCH_USERPROFILE_REQUEST
}
}
export const fetchUserProfileSuccess = (userprofiles) => {
return {
type: FETCH_USERPROFILE_SUCCESS,
payload: userprofiles
}
}
export const fetchUserProfileFailure = (error) => {
return {
type: FETCH_USERPROFILE_FAILURE,
payload: error
}
}
export const fetchUserProfile = () => {
return async dispatch => {
dispatch(fetchUserProfileRequest)
try {
const responsedata = await Parse.Cloud.run("GetUserProfileForUsername", params);
const userprofiles = responsedata;
dispatch(fetchUserProfileSuccess(userprofiles))
}
catch (error) {
const errorMessage = error.message
dispatch(fetchUserProfileFailure(errorMessage))
}
}
}
Please ignore parts of code which do not make it relevant, its straight from the project
You mixed up the order of your arguments, so this.props.dispatch is actually your state!
You need to change
export default connect(mapDispatchtoProps, mapStatetoProps)(ProfileHeader)
to:
export default connect(mapStatetoProps, mapDispatchtoProps)(ProfileHeader)
If you can switch to function components and the useSelector/useDispatch hooks you should. This is the current recommended approach and it's easier to use.
Related
I'm trying to learn redux-observables but I seem to be having an issue getting my app to return data. I keep getting the error below and I'm not sure where I'm going wrong or what the error actually means.
I'm trying to learn redux-observables but I seem to be having an issue getting my app to return data. I keep getting the error below and I'm not sure where I'm going wrong or what the error actually means.
I'm trying to learn redux-observables but I seem to be having an issue getting my app to return data. I keep getting the error below and I'm not sure where I'm going wrong or what the error actually means.
I'm trying to learn redux-observables but I seem to be having an issue getting my app to return data. I keep getting the error below and I'm not sure where I'm going wrong or what the error actually means.
ERR: fetchData is not a function
I need help
Contsants
export const FETCH_DATA = "FETCH_DATA";
export const FETCH_DATA_FAIL = "FETCH_DATA_FAIL ";
Action
import { FETCH_DATA, FETCH_DATA_FAIL } from "../contsants/contsants";
export const fetchData = (exampleData = {}) => ({
type: FETCH_DATA,
payload: exampleData
});
export const fetchDataFail = () => ({
type: FETCH_DATA_FAIL
});
Store
import { createStore } from "redux";
import rootReducer from "../Reducer/reducer";
const store = createStore(rootReducer);
export default store;
Reducer
import { FETCH_DATA, FETCH_DATA_FAIL } from "../contsants/contsants";
import { combineReducers } from "redux";
const initialState = {};
export const exampleData = (state = initialState, action: any) => {
switch (action.type) {
case FETCH_DATA:
return action.payload;
case FETCH_DATA_FAIL:
return {};
default:
return state;
}
};
export default combineReducers({
exampleData
});
Epics
import "rxjs";
import axios from "axios";
import { from, of } from "rxjs";
import { mergeMap, map, catchError } from "rxjs/operators";
import { ofType } from "redux-observable";
import { FETCH_DATA } from "../contsants/contsants";
import { fetchData, fetchDataFail } from "../Actions/action"
export const exampleEpic = (action$: any) =>
action$.pipe(
ofType(FETCH_DATA),
mergeMap((action) =>
from(axios.get("jsonplaceholder.typicode.com/todos/1")).pipe(
map((response) => fetchData(response.data)),
catchError(() => of(fetchDataFail()))
)
)
);
App
import { fetchData } from './Actions/action'
import { connect } from "react-redux";
function App(data: any, fetchData: any) {
const handleClickShowsTodos = () => {
fetchData()
console.log(data);
}
return (
<div>
<input type="text" />
<button onClick={handleClickShowsTodos}>ShowsTodo</button>
</div>
);
}
const mapStateToProps = (state: any) => {
return {
data: state
};
};
function mapDispatchToProps(dispatch: any) {
return {
fetchData: () => {
console.log('dispatch')
dispatch(fetchData())
}
};
}
export default connect(mapStateToProps, mapDispatchToProps)(App);
I'm new to React, Redux and have been following tutorials on the topic. I'm come across a lot of issues that I've been able to resolve but I've come across an issue I can't resolve. I set up store, and can even view it through Chrome's Redux Tools and it show correctly, however when I try and dispatch to the Store, I always get a Cannot read property 'dispatch' of undefined error. I have followed numerous tutorials letter for letter, and am still stuck with the same error message.
Index.Js
import Layout from '../components/layout/Layout';
import Home from '../components/Home';
import { getRooms } from '../redux/actions/roomActions';
import { wrapper } from '../redux/store';
export default function Index() {
return (
<Layout>
<Home />
</Layout>
);
}
export const getServerSideProps = wrapper.getServerSideProps(
async ({ req, store }) => {
await store.dispatch(getRooms(req));
}
);
roomConstants.js
export const ALL_ROOMS_SUCCESS = 'ALL_ROOMS_SUCCESS';
export const ALL_ROOMS_FAIL = 'ALL_ROOMS_FAIL';
export const CLEAR_ERRORS = 'CLEAR_ERRORS';
reducer.js
import { combineReducers } from 'redux';
import { allRoomsReducer } from './roomReducers';
const reducer = combineReducers({
allRooms: allRoomsReducer,
});
export default reducer;
Store.js
import { createStore, applyMiddleware } from 'redux';
import { HYDRATE, createWrapper } from 'next-redux-wrapper';
import thunkMiddleware from 'redux-thunk';
import reducers from './reducers/reducers';
const bindMiddleware = (middleware) => {
if (process.env.NODE_ENV !== 'production') {
const { composeWithDevTools } = require('redux-devtools-extension');
return composeWithDevTools(applyMiddleware(...middleware));
}
return applyMiddleware(...middleware);
};
const reducer = (state, action) => {
if (action.type === HYDRATE) {
const nextState = {
...state,
...action.payload,
};
return nextState;
} else {
return reducers(state, action);
}
};
const initStore = () => {
return createStore(reducer, bindMiddleware([thunkMiddleware]));
};
export const wrapper = createWrapper(initStore);
roomReducer.js
import {
ALL_ROOMS_SUCCESS,
ALL_ROOMS_FAIL,
CLEAR_ERRORS,
} from '../constants/roomConstants';
// All rooms reducer
export const allRoomsReducer = (state = { rooms: [] }, action) => {
switch (action.type) {
case ALL_ROOMS_SUCCESS:
return {
roomsCount: action.payload.roomsCount,
resPerPage: action.payload.resPerPage,
filteredRoomsCount: action.payload.filteredRoomsCount,
rooms: action.payload.rooms,
};
case ALL_ROOMS_FAIL:
return {
error: action.payload,
};
case CLEAR_ERRORS:
return {
...state,
error: null,
};
default:
return state;
}
};
roomAcion.js
import axios from 'axios';
import absoluteUrl from 'next-absolute-url';
import {
ALL_ROOMS_SUCCESS,
ALL_ROOMS_FAIL,
CLEAR_ERRORS,
} from '../constants/roomConstants';
//Clear errors
export const clearErrors = () => async (dispatch) => {
return dispatch({
type: CLEAR_ERRORS,
});
};
// Get all rooms
export const getRooms = (req) => async (dispatch) => {
try {
const { origin } = absoluteUrl(req);
const { data } = await axios.get(`${origin}/api/rooms`);
dispatch({
type: ALL_ROOMS_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: ALL_ROOMS_FAIL,
payload: error.response.data.message,
});
}
};
in index.js, your getServerSideProps function should read this;
export const getServerSideProps = wrapper.getServerSideProps((store) => async ({ req }) => {
await store.dispatch(getRooms(req));})
Use the old version of next-redux-wrapper like 6.0.2
I try to create a Redux and I have a problem when I try to do dispatch is not working.
Action file, userActions.js:
export const setId = () => {
console.log("Enter to set id func");
return {
type: 'SET_ID'
}
}
Reducer file, userReducer.js:
const INITIAL_STATE = {
id: "",
email: "",
name: "",
};
const userReducer = (state = INITIAL_STATE, action) => {
console.log('Enter to userReducer');
switch (action.type) {
case "SET_ID": {
// console.log(action.payload);
}
default: {
return state;
}
}
}
export default userReducer;
combineReducers file:
import userReducer from "./userReducer";
import { combineReducers } from "redux";
const allReducers = combineReducers({
userReducer: userReducer
})
export default allReducers;
App.js file:
import React from 'react';
import Routes from "./Routes";
import { createStore } from "redux";
import allReducer from "./app/reducers";
import { Provider } from "react-redux";
const store = createStore(
allReducer
);
const App = () => {
return (
<Provider store={store}>
<Routes />
</Provider>
);
};
export default App;
In login screen file, I have button when I click on him call to dispatch to "setId" action.
Here some of my code from Login.js:
import { useDispatch } from 'react-redux';
import { setId } from '../actions/userActions';
handleLoginResult = (error, user) => {
console.log('Enter to handleLoginResult');
if (error !== "") {
this.setState({ generalError: error });
} else {
const dispatch = useDispatch();
console.log('uid: ', user.user.uid);
dispatch(setId());
alert("Login!");
}
}
What is the problem and why is not enter to setId action?
You can try with like this
const userReducer = (state = INITIAL_STATE, action) =>dispatch =>{
console.log('Enter to userReducer');
switch (action.type) {
case "SET_ID": {
// console.log(action.payload);
}
default: {
return state;
}
}
}
I didn't quite understand your question, but I'll give you an example of an action of mine
export const register_user = ({ name, email, password, password_confirmation }) => {
return dispatch => {
dispatch(
{
type: CREATE_USER
}
)
let url = "/users"
Axios.post(`${SERVER}${url}`, {
"user": {
"name": name,
"email": email,
"password": password,
"password_confirmation": password_confirmation
}
})
.then(() => {
Alert.alert('Registrado com sucesso!')
registerUserSuccess(dispatch)
})
.catch((err) => {
registerUserError(err, dispatch)
})
}
}
const registerUserSuccess = (dispatch) => {
dispatch(
{
type: CREATE_USER_SUCCESS
}
)
this.props.navigation.navigate('Login')
}
const registerUserError = (err, dispatch) => {
dispatch(
{
type: CREATE_USER_ERROR
}
)
Alert.alert('Algo deu errado, verifique suas credenciais.')
}
The type is exported from my reducer.
And the register_user constant is imported and used on my register screen.
Hooks cannot be used inside a function. They need to declared directly inside the functional component.
Also useDispatch hook cannot be used inside a class component, you must use connect for a class component.
Assuming you have a class component, judging by how you use this.setState, you would write your code like
class Login extends React.Component {
...
handleLoginResult = (error, user) => {
console.log('Enter to handleLoginResult');
if (error !== "") {
this.setState({ generalError: error });
} else {
const dispatch = this.props;
console.log('uid: ', user.user.uid);
dispatch(setId());
alert("Login!");
}
}
...
}
export default connect()(Login)
If however you were to write login as a functional component, you would write it like
const Login = (props) => {
const dispatch = useDispatch();
const [state, setState] = useState({});
...
const handleLoginResult = (error, user) => {
console.log('Enter to handleLoginResult');
if (error !== "") {
setState({ generalError: error });
} else {
console.log('uid: ', user.user.uid);
dispatch(setId());
}
}
...
}
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!
**Hello! my problem is my state is not uploading, is always empty altough my actions brings data correct. Can anyone give me some help of what am I doing wrong ?
I think is something with the name or the combine reducers part.
Maybe I am not accesing data correct with my reducer or something like that **
The object I receive from the api call has this format {categories: Array(4), items: Array(50)}
Component
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import ItemList from '../components/ItemList/ItemList';
import { getItems } from './actions'
class ItemListContainer extends PureComponent {
async componentDidMount() {
const { getItems } = this.props;
await getItems()
console.log(this.props)
}
render() {
return <ItemList />;
}
}
const mapStateToProps = state => (
{
items: state.items.items,
});
const mapDispatchToProps = dispatch =>
bindActionCreators(
{
getItems,
},
dispatch,
);
export default connect(mapStateToProps, mapDispatchToProps)(ItemListContainer);
actions.js
export const GET_ITEMS = 'GET_ITEMS';
export const GET_ITEM = 'GET_ITEM';
export const GET_ITEM_DESCRIPTION = 'GET_ITEM_DESCRIPTION';
export function getItems(query) {
return async function (dispatch) {
// const res = await fetch(`http://localhost:3000/api/items?q=${query}`)
const res = await fetch(`http://localhost:3000/api/items?q=ipad`)
const items = await res.json()
return dispatch({
type: 'GET_ITEMS',
items: items.items,
})
}
}
reducer.js
import { GET_ITEMS } from './actions';
const initialState = {
items: [],
itemsLoaded: false,
};
export default function(state = initialState, action) {
const { type, data } = action;
switch (type) {
case GET_ITEMS:
return {
...state,
items: data,
itemsLoaded: true,
};
default: {
return {
...state
}
}
}
}
I was accessing { data} in the reducer which of course it was empty. The correnct action was items.