'onFetchEventDetail' function can't be called on componentDidMount.It shows this.props.onFetchEventDetail is not a function. I have made actions,reducers,selectors and saga for this function, all i need is this function to be triggered. Code is as follows:
import React, {Component} from 'react';
import {compose} from "redux";
import './EventDetailPage.css';
import PropTypes from 'prop-types';
import {requestEventDetail} from "./actions";
import {makeSelectEventDetail} from "./selectors";
import {createStructuredSelector} from "reselect";
import reducer from "./reducer";
import saga from "./saga";
import {connect} from "react-redux";
import injectReducer from "utils/injectReducer";
import injectSaga from "utils/injectSaga";
export class EventDetail extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log("eventdetail:::" + this.props.match.params.eventId);
this.props.onFetchEventDetail();
}
render() {
return (
<div>
...
</div>
);
}
}
EventDetail.propTypes = {
eventId: PropTypes.string,
onLoadFetchEventDetail: PropTypes.func,
};
export function mapDispatchToProps(dispatch) {
return {
onFetchEventDetail: evt =>
dispatch(requestEventDetail())
}
}
const mapStateToProps = createStructuredSelector({
eventDetail: makeSelectEventDetail()
});
const withConnect = connect(
mapStateToProps,
mapDispatchToProps
);
const withReducer = injectReducer({key: "eventDetailPage", reducer});
const withSaga = injectSaga({key: "eventDetailPage", saga});
export default compose(
withReducer,
withSaga,
withConnect
)(EventDetail);
Related
My question is about why my Cities component in React project do not see any props. What is wrong here? Also i can't understand why reducer do not update state from axios async. What is wrong here?
Here is github link for this project: https://github.com/technoiswatchingyou/reg-form-demo
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import { citiesRequestReducer } from './citiesRequestReducer';
const rootReducer = combineReducers({
cities: citiesRequestReducer
});
const store = createStore(rootReducer, applyMiddleware(thunk));
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
registerServiceWorker();
App.js
import React, { Component } from 'react';
import './App.css';
import Cities from './cities';
class App extends Component {
render() {
return (
<div className="App">
<Cities />
</div>
);
}
}
export default App;
cities.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { citiesRequestAction } from './citiesRequestAction';
import { bindActionCreators } from 'redux';
class Cities extends Component {
componentDidMount() {
this.props.onCitiesRequest();
console.log(this.props);
}
render() {
return (
<select className="custom-select">
{this.props.cities.map(city => (
<option key={city.id}>{city.name}</option>
))}
</select>
);
}
}
const mapStateToProps = state => ({
cities: state.cities
});
const mapDispatchToProps = dispatch => {
return bindActionCreators(
{
onCitiesRequest: citiesRequestAction
},
dispatch
);
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Cities);
citiesRequestReducer.js
import { CITIES_REQUEST } from './citiesRequestAction';
const initialState = [];
export function citiesRequestReducer(state = initialState, action) {
switch (action.type) {
case CITIES_REQUEST:
return {
...state,
cities: action.payload
};
default:
return state;
}
}
citiesRequestAction.js
import axios from 'axios';
export const CITIES_REQUEST = 'CITIES_REQUEST';
const GET_CITIES_URL = 'https://www.mocky.io/v2/5b34c0d82f00007400376066?mocky-delay=700ms';
function citiesRequest(cities) {
return {
type: CITIES_REQUEST,
payload: cities
};
}
export function citiesRequestAction() {
return dispatch => {
axios.get(GET_CITIES_URL).then(response => {
dispatch(citiesRequest(response.data.cities));
});
};
}
So problem was in citiesRequestReducer. Instead of return {...state, cities: action.payload} I just need to return action.payload.
I cant figure out what is going on. I have redux-thunk setup just like always. For some reason that I can not figure out I get the error: Error: Actions must be plain objects. Use custom middleware for async actions. can anyone help me figure this error out?
Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './app';
import './index.css';
ReactDOM.render(
<App />,
document.getElementById('root')
);
CreateStore.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducers from './reducers';
export default function configureStore(initialState) {
return createStore(
reducers,
initialState,
applyMiddleware(thunk)
);
}
app.js
import React, { Component } from 'react';
import Routes from './Routes';
import {Provider} from 'react-redux';
import configureStore from './configureStore';
const store = configureStore();
class App extends Component {
render(){
return (
<Provider store={store}>
<Routes/>
</Provider>
);
}
}
export default App;
Today.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { autoLocate } from '../actions';
import { Button } from './Common'
class Today extends Component {
componentDidMount() {
this.props.fetchTodayWeather('http://
api.wunderground.com/api/cc9e7fcca25e2
ded/geolookup/q/autoip.json');
}
render() {
return (
<div>
<div style={styles.Layout}>
<div><Button> HAHAH </Button></div>
<div><Button> Weather Now </Button></div>
</div>
</div>
);
}
}
const mapStateToProps = state => {
const loading = state.locate.loading;
const located = state.locate.autolocation;
return{ loading, located };
};
const mapDispatchToProps = (dispatch) => {
return {
fetchTodayWeather:(Url) => dispatch(autoLocate(Url))
};
};
export default connect(mapStateToProps,mapDispatchToProps)(Today);`
autoLocate.js
import { AUTODATA,
AUTOLOCATING
} from './types';
export const autoLocate = (url) => {
return (dispatch) => {
dispatch({ type: AUTOLOCATING });
fetch(url)
.then(data => fetchSuccess(dispatch, data))
};
};
const fetchSuccess = (dispatch, data) => {
dispatch({
type: AUTODATA,
payload: data
});
};
Been trying to figure this out for the past 2-3 hours.
The app starts from running on the browser and displays the error that this.props.fetchAPOD is not a function (screenshots at the far bottom) but it clearly is in my action creator. Also in my container it says the error that "Argument of type 'typeof "C:/Users/pfftd/projectcrystal/src/actions/crystalActions"' is not assignable to parameter of type 'ActionCreatorsMapObject' when I assign the actions to mapDisPatchToProps (which is the same EXACT code I see in Microsoft's react/typescript start-kit guide: https://github.com/Microsoft/TypeScript-React-Starter
Here is my code:
container Crystal.tsx
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import Crystal from '../components/Crystal';
import * as actions from '../actions/crystalActions';
import {
ApodSTATE
} from '../types';
export function mapStateToProps({ APOD }: ApodSTATE ) {
return {
APOD
};
}
export function mapDispatchToProps( dispatch: any ) {
return bindActionCreators( actions, dispatch );
}
export default connect( mapStateToProps, mapDispatchToProps )( Crystal );
App.tsx (file that contains the store and the provider)
import * as React from 'react';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import { createLogger } from 'redux-logger';
import allReducers from './reducers';
import Crystal from './components/Crystal';
// import { ApodSTATE } from './types';
const logger = createLogger({
level: 'info',
collapsed: true
});
const store: any = createStore(allReducers, applyMiddleware(thunk, logger));
class App extends React.Component<any, any> {
render() {
return (
<Provider store={store}>
<Crystal />
</Provider>
);
}
}
export default App;
crystalActions.tsx
export const FETCH_APOD = 'FETCH_APOD';
export type FETCH_APOD = typeof FETCH_APOD;
export interface FetchApod { type: FETCH_APOD };
export const fetchAPOD = () => {
return ( dispatch: any ) => {
dispatch({
type: FETCH_APOD
});
};
};
types (index.tsx)
export interface TableName {
TableName: string;
}
export interface ApodACTIONS {
type: string;
fetchAPOD?: () => {};
};
export interface ApodSTATE {
APOD: {};
}
export enum actionTypes {
FETCH_APOD
}
component Crystal.tsx
import * as React from 'react';
// import { ApodSTATE } from '../types';
class Crystal extends React.Component<any, any> {
constructor(props: any) {
super(props);
this.printTest = this.printTest.bind(this);
}
componentDidMount() {
this.printTest();
this.props.fetchAPOD();
}
printTest() {
setTimeout(() => {
console.log(this.props);
}, 1500);
}
render() {
return (
<div>
<h2>Project Crystal initiation</h2>
<h3>Test</h3>
</div>
);
}
}
export default Crystal;
Screenshots of a closer look:
Are you importing the right component? In App.tsx you have
import Crystal from './components/Crystal';
Should it not be
import Crystal from './containers/Crystal';
It looks like you aren't using the container component and are instead using the presentational one
On writing my first RN application, I have got the below error message on executing the code,
"undefined is not a function (evaluating '_ConfigureStore2.default.dispatch(CategoryAction.categoryView())')"
ConfigureStore.js:
import {createStore, applyMiddleware} from 'redux';
import reducers from '../reducers';
import thunk from 'redux-thunk';
var middlewares = applyMiddleware(thunk);
export default function configureStore(initialState) {
return createStore(reducers, initialState, middlewares);
}
CategoryContainer.js:
import React, { Component } from 'react';
import stores from '../stores/ConfigureStore';
import * as CategoryAction from '../actions/CategoryAction';
stores.dispatch(CategoryAction.categoryView());
class CategoryContainer extends Component {
}
CategoryAction.js:
import * as actionTypes from './ActionTypes';
import AppConstants from '../constants/AppConstants';
export function categoryView() {
const categories = ['CATEGORY1', 'CATEGORY2'];
return {
type: "CATEGORY_VIEW",
categories: categories
};
}
CategoryReducer.js:
const initialState = {
categories:[],
}
export default function categoryReducer (state = initialState, action) {
switch (action.type) {
case CATEGORY_VIEW:
return Object.assign({}, state, {
categories: action.categories
});
}
}
Even i tried the below approach in CategoryContainer.js, but still got the same error,
import { categoryView } from '../actions/CategoryAction';
stores.dispatch(categoryView());
Kindly assist to solve the issue.
Give this a shot:
CategoryAction.js
export default class CategoryAction {
categoryView = () => {
const categories = ['CATEGORY1', 'CATEGORY2'];
return {
type: "CATEGORY_VIEW",
categories: categories
};
}
}
CategoryContainer.js
import React, { Component } from 'react';
import stores from '../stores/ConfigureStore';
import CategoryAction from '../actions/CategoryAction';
stores.dispatch(CategoryAction.categoryView());
class CategoryContainer extends Component {
}
On changing the ConfigureStore.js as below solves the issue.
import {createStore, applyMiddleware} from 'redux';
import reducers from '../reducers';
import thunk from 'redux-thunk';
/*var middlewares = applyMiddleware(thunk);
export default function configureStore(initialState) { //default is undefined
return createStore(reducers, initialState, middlewares);
}*/
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
const store = createStoreWithMiddleware(reducers);
export default store;
I wrote the same issue on https://github.com/erikras/redux-form/issues/1655 .
I've get an error reduxForm.js:644Uncaught TypeError: Cannot read property 'wrapped' of undefined so far when I have started migrating v6.0.1 from v5.3.2 .
To make a problem easier, I am now only testing only these 5 files, but still the error rises.
Please tell me how I should do.
App.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import {
Provider
} from 'react-redux';
import store from '-/store';
import Catalogue from '-/containers/Catalogue';
ReactDOM.render(
(
<Provider store={store}>
<Catalogue />
</Provider>
),
document.getElementById('app')
);
containers/Catalogue.js
import {
connect
} from 'react-redux';
import Catalogue from '-/components/Catalogue';
const mapStateToProps = (state) => {
return {
};
};
const mapDispatchToProps = (dispatch) => {
return {
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Catalogue);
components/Catalogue.jsx
import React, {
Component
} from 'react';
import {
reduxForm
} from 'redux-form';
class Catalogue extends Component {
render() {
return (
<div />
);
}
}
export default reduxForm({
form: 'catalogue'
})(Catalogue);
store.js
import {
createStore,
} from 'redux';
import reducers from '-/reducers';
const store = createStore(
reducers,
);
export default store;
and reducers/index.js
import {
combineReducers
} from 'redux';
import {
reducer as formReducer
} from 'redux-form';
export default combineReducers(
{
form: formReducer
}
);