How do I resolve "sourceSelector is not a function" in React? - javascript

I'm working in a React project and I'm trying to dispatch an action to make a get request. However I'm receiving 'TypeError: sourceSelector is not a function'.
Here is my code from ViewDocument.js
import React from 'react';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import AccountFlowHeader from 'components/Header/AccountFlowHeader';
import { LoadingModal } from 'components/Modals';
import { policiesSelector } from '../Policies/Policies.redux';
import { logOutAction } from '../Login/Login.actions';
import BasePage from '../BasePage';
import { getPolicyStatus } from './PolicyViewDocument.actions';
class PolicyViewDocument extends BasePage {
constructor(props) {
super(props);
this.state = {
showLoaderForPolicyDocument: false,
};
}
componentDidMount() {
super.componentDidMount();
const { currentPolicy: { contractNum } } = this.props;
this.setState({ showLoaderForPolicyDocument: true }, () => {
this.props.getPolicyStatus(contractNum, () => {
this.setState({ showLoaderForPolicyDocument: false });
}, (code) => {
if (code === 'C002') {
console.log(code);
} else {
this.setState({
showLoaderForPolicyDocument: false,
});
}
});
});
}
const mapDispatchToProps = {
getPolicyStatus,
};
export default withRouter(connect(policiesSelector, mapDispatchToProps, { logOutAction })(PolicyViewDocument));
And here is my code from Actions.js
import axios from 'axios';
import urls from 'constants/urls';
import { getErrorCode } from 'utils/common';
import globals from 'constants/globals';
export const getPolicyStatus = (contractNum, scb, fcb) => {
axios({
url: urls.getPolicyStatus(contractNum),
method: 'get',
timeout: globals.timeout,
})
.then((response) => {
if (response.status === 200 && !response.data.errors) {
if (scb) scb(response.data);
} else if (fcb) fcb(getErrorCode(response));
})
.catch((e) => { if (fcb) fcb(getErrorCode(e.response)); });
};
I'm sure it has something to do with how I'm using mapDispatchToProps however I haven't been able to resolve.

Why are you calling super.componentDidMount?? I guess you have used sourceSelector in your parent component, because I am not seeing any sourceSelector thing in your share code snippets.
Try removing super.componentDidMount from here.

Related

problem with react export 'withRouter' (imported as 'withRouter') was not found in 'react-router'

I was following a tutorial until I got this error. I know that this is caused by some changes on react-router-dom, but I have no idea of how to change this code to the new version, can you give me any suggestions?
import React, { Component } from "react";
import { withRouter } from "react-router";
const parseJwt = (token) => {
try {
return JSON.parse(atob(token.split('.')[1]));
} catch (e) {
return null;
}
};
class AuthVerify extends Component {
constructor(props) {
super(props);
props.history.listen(() => {
const user = JSON.parse(localStorage.getItem("user"));
if (user) {
const decodedJwt = parseJwt(user.accessToken);
if (decodedJwt.exp * 1000 < Date.now()) {
props.logOut();
}
}
});
}
render() {
return <div></div>;
}
}
export default withRouter(AuthVerify);

componentDidUpdate() is not firing when component is wrapped in HOC

I have HOC component which wraps all the page Components. The page component has pagination, when user clicks next, the route params changes and the difference between route param and state is compared in componentDidUpdate and then api is called. The code works on without wrapping HOC.
Routes
import React from 'react';
import { Redirect, Route, Switch, withRouter } from 'react-router-dom';
import hocWrapper from './hocWrapper'
import Dashboard from './components/screens/dashboard/Dashboard';
import Movies from './components/screens/movies/Movies';
const Routes = (props) => (
<Switch style={{ position: 'absolute' }}>
<Route exact path="/all/page:pageNumber" component={hocWrapper(Dashboard)} />
<Route exact path="/movies/page:pageNumber" component={Movies} />
</Switch>
);
export default withRouter(Routes);
HOC wrapper Component
import React, { useEffect } from 'react';
import { useDispatch } from "react-redux";
import { searchTextAction } from './containers/actions/userActions'
export default function (ComposedClass) {
const ClosedRouteForUser = (props) => {
const dispatch = useDispatch();
useEffect(() => {
console.log(window.location.pathname)
if (window.location.pathname !== `/search/page1` &&
window.location.pathname.includes('details') === false) {
dispatch(searchTextAction(''))
}
}, []);
return <ComposedClass {...props} />;
};
return ClosedRouteForUser;
}
Page Component
import React, { Component } from 'react'
import apiCall from '../../../services/apiCall';
import { trendingURL } from '../../../services/apiURL'
import MediaList from '../../common/MediaList'
import { withRouter } from 'react-router-dom';
class Dashboard extends Component {
state = {
dataList: [],
refresh: false,
pageNumber: this.props.match?.params && this.props.match.params.pageNumber,
}
async componentDidMount() {
try {
if (this.props.match?.params.routedFrom) {
localStorage.setItem("routedFrom", this.props.match.params.routedFrom)
}
console.log('cd mount')
window.scrollTo(0, 0)
this.setState({ refresh: true })
let data = { page: 1, media_type: "all" }
let apiData = await apiCall(trendingURL, data)
this.setState({ dataList: apiData.results, refresh: false })
} catch (error) {
console.log(error)
}
}
async componentDidUpdate(prevProps, prevState) {
if (this.props.match.params.pageNumber !== this.state.pageNumber) {
console.log('cd updates')
let data = { page: this.props.match.params.pageNumber, media_type: "all" }
let apiData = await apiCall(trendingURL, data)
this.setState({
dataList: apiData.results,
pageNumber: this.props.match.params.pageNumber,
refresh: false
})
}
}
pageNavigate = (value) => {
window.scrollTo(0, 0)
this.setState({ pageNumber: value })
this.props.history.replace({ pathname: `/all/page${value}` })
}
previous = () => {
this.pageNavigate(parseInt(this.props.match.params.pageNumber) - 1)
}
next = () => {
this.pageNavigate(parseInt(this.props.match.params.pageNumber ?
this.props.match.params.pageNumber :
1) + 1)
}
render() {
const { dataList, refresh } = this.state
return (
<MediaList
listData={dataList}
refresh={refresh}
previous={this.previous}
next={this.next}
/>
)
}
}
export default withRouter(Dashboard)

React + Redux binded state has no data

After one of the Redux tutorials decided to implement that facny action->reducer->store->view chain for simple app with only login part.
Seems like all setted up but when I run my app - in mapStateToProps(currentState) no any sign of the any custom state fields which I expected to see! (default state from reducer). But the action function is fine, as you can see on the screenshot
I can't see whats wrong here so, decided to ask it.
So here is the code
So, first of all - store.js
import { createStore, applyMiddleware } from 'redux';
import rootReducer from '../reducers';
import thunk from 'redux-thunk';
export default function configureStore(initialState) {
const store = createStore(rootReducer, initialState, applyMiddleware(thunk));
if (module.hot) {
module.hot.accept('../reducers', () => {
const nextRootReducer = require('../reducers');
store.replaceReducer(nextRootReducer);
});
}
return store;
}
then login reducer
const initialState = {
user: {
name: '',
password: ''
},
fetching: false
}
export default function login(state = initialState, action) {
switch (action.type) {
case LOGIN_REQUEST: {
return { ...state, fetching: true }
}
case LOGIN_SUCCESS: {
return { ...state, user: action.data, fetching: false }
}
case LOGIN_FAIL: {
return { ...state, user: -1, fetching: false }
}
default: {
return state;
}
}
}
and the root (reducers/index.js):
import login from './login/login';
import { combineReducers } from 'redux'
export default combineReducers({
login
});
the action
import {
LOGIN_REQUEST,
LOGIN_SUCCESS,
LOGIN_FAIL
} from '../../constants/login.js';
export function onLoginAttempt(userData) {
return (dispatch) => {
dispatch({
type: LOGIN_REQUEST,
user: userData
})
tryLogin(userData);
}
};
function tryLogin(userData) {
let url = 'SignIn/Login ';
return (dispatch) => {
axios.post(url, userData)
.then((response) => dispatch({
type: LOGIN_SUCCESS,
data: response.data
})).error((response) => dispatch({
type: LOGIN_FAIL,
error: response.error
}))
}
};
So here is entrance point:
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import App from './containers/app.js';
import configureStore from './store/configureStore';
let store = createStore(configureStore);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("content")
);
and here is the app.js (Login is just sompe custom div with two fields nothing special)
import React, { Component } from 'react';
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux';
import Login from '../components/login/Login';
import * as pageActions from '../actions/login/login'
class App extends Component {
render() {
const { user, fetching } = this.props;
const { onLoginAttempt } = this.props.pageActions;
return <div>
<Login name={user.name} password={user.password} fetching={fetching} onLoginAttempt={onLoginAttempt} />
</div>
}
}
function mapStateToProps(currentState) {
return {
user: currentState.user,
fetching: currentState.fetching
}
}
function mapDispatchToProps(dispatch) {
return {
pageActions: bindActionCreators(pageActions, dispatch)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
I see that you have state which looks like:
reduxState = {
login: {
user: {
name: '',
password: ''
},
fetching: false
}
}
but then you try to access properties that don't exist.
function mapStateToProps(currentState) {
return {
user: currentState.user,
fetching: currentState.fetching
}
}
I think you need to:
function mapStateToProps(currentState) {
return {
user: currentState.login.user,
fetching: currentState.login.fetching
}
}
You have this line let store = createStore(configureStore); on your entry point. However, inside configureStore, you have a call to createStore()
Basically you're calling something like createStore(createStore(reducers)). That's probably the cause of the problem.
You should probably call it like
let store = configureStore( /* pass the initial state */ )

React Native: Possible Unhandled Promise Rejection (id: 0)

so i'm trying to learn more about Redux through React-Native.
i'm trying to issue a HTTPS request with Axios to pull data from a web-server. everything runs fine, i console log the action and the payload is the data i need. but it still throws a 'Cannot read property 'data' of null' TypeError.
the following is my code:
import React, { Component } from 'react';
import ReduxThunk from 'redux-thunk';
import { StackNavigator } from 'react-navigation';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import reducers from '../reducers';
import ReduxTestObj from '../components/ReduxTestObj';
export default class ReduxTest extends Component {
render() {
return (
<Provider store={createStore(reducers, {}, applyMiddleware(ReduxThunk))}>
<ReduxTestObj />
</Provider>
);
}
}
Here is the ReduxTestObj
import React, { Component } from 'react';
import _ from 'lodash';
import { View } from 'react-native';
import { connect } from 'react-redux';
import DevBanner from './DevBanner';
import Header from './Header';
import { actionCreator } from '../actions';
class ReduxTestObj extends Component {
componentWillMount() {
this.props.actionCreator('urlIWantToGoTo');
}
getBannerText() {
if (this.props.loading) {
return 'PULLING DATA. GIVE ME A SECOND';
}
const rObj = _.map(this.state.data[1].recipient_list);
const rName = [];
for (let i = 0; i < rObj.length; i++) {
rName[i] = rObj[i].team_key.substring(3);
}
const winnerMSG = `Teams ${rName[0]}, ${rName[1]}, ${rName[2]}, ${rName[3]} Won`;
return winnerMSG;
}
render() {
return (
<View>
<Header
text={'Redux Testing'}
/>
<DevBanner
message={this.getBannerText()}
/>
</View>
);
}
}
const mapStateToProps = state => {
return {
data: state.tba.data,
loading: state.tba.loading
};
};
export default connect(mapStateToProps, { actionCreator })(ReduxTestObj);
Here is the Action Creator
import axios from 'axios';
import { TBA_PULL } from './Types';
export const actionCreator = (url) => {
return (dispatch) => {
axios({
method: 'get',
url,
responseType: 'json',
headers: {
'Auth-Key':
'Hidden For Obvious Reasons'
},
baseURL: 'theBaseUrlOfTheWebsite'
}).then(response => {
dispatch({ type: TBA_PULL, payload: response.data });
});
};
};
And Here is the Reducer
import { TBA_PULL } from '../actions/Types';
const INITIAL_STATE = { data: [], loading: true };
export default (state = INITIAL_STATE, action) => {
console.log(action);
switch (action.type) {
case TBA_PULL:
return { ...state, loading: false, data: action.payload };
default:
return state;
}
};
As stated above, the console.log(action) prints out and the data it has is correct. yet it continues to throw the following error:
Error1
I've tried changing things around, googling, searching, gutting out the Action Reducer to make it as basic as possible by just returning a string. and it refuses to work.
Has anyone run into an issue similar to this or know how to fix it?
Thank you for your time.
EDIT: i also console logged 'this' as the first line of getBannerText() in ReduxTestObj and it returned successfully this.props.data as the data i want and this.props.loading as false. Yet it still throws the same error.
Welp. I guess i was just making a mistake.
i was calling This.state.data instead of this.props.data in getBannerText().
that solved the issue.

Redux with React Native - unable to access property function

I have been trying to learn to This is a simple login, logout app using Redux. On pressing the Login Button from Display.js, the login_action function should be called. But an error is showing with title Cannot read property login_action of undefined. I tried logging the props in Display.js and I am able to see the functions in the logs but somehow the functions aren't being called. What is it that I'm missing or unable to find out?
Basic App :
/* App.js */
import React, {Component} from 'react';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import * as reducers from './reducers';
import SceneContainer from './containers/SceneContainer';
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
const reducer = combineReducers(reducers);
const store = createStoreWithMiddleware(reducer);
export default class App extends Component {
render() {
return (
<Provider store={store}>
<SceneContainer />
</Provider>
);
}
}
Container:
/* containers/SceneContainer.js */
'use strict';
import React, {Component, PropTypes} from 'react';
import Display from '../components/display';
import * as loginActions from '../actions/';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
class SceneContainer extends Component {
constructor(props) {
super(props);
}
render() {
const {actions} = this.props;
console.log(actions);
return (
<Display {...actions}/>
);
}
}
SceneContainer.propTypes = {
user: PropTypes.object.isRequired,
actions: PropTypes.object.isRequired
};
function mapStateToProps(state) {
return {user: state.auth.user};
}
function mapDispatchToProps(dispatch) {
console.log(loginActions);
return {
actions: bindActionCreators(loginActions, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(SceneContainer);
Component :
/* components/display.js */
import React, {Component, PropTypes} from 'react';
import {
View,
Text,
StyleSheet,
TouchableHighlight,
} from 'react-native';
class Display extends Component {
constructor(props) {
super(props);
console.log(props.login_action);
}
onLoginPress() {
this.props.login_action({
username: 'ranat',
password: 'password'
});
}
onLogoutPress() {
this.props.logout_action();
}
render() {
return (
<View>
<TouchableHighlight onPress={this.onLoginPress}>
<Text>Login</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.onLogoutPress}>
<Text>Logout</Text>
</TouchableHighlight>
</View>
);
}
}
Display.propTypes = {
logout_action: PropTypes.func.isRequired,
login_action: PropTypes.func.isRequired
};
export default Display;
Actions file :
/* actions/index.js */
import {LOGIN_ACTION, LOGOUT_ACTION, LOGIN_SUCCESS, LOGIN_FAILURE} from './actionTypes';
export var login_action = (userCredentials) => {
if(userCredentials.username === 'ranat' && userCredentials.password === 'password') {
return {
type: LOGIN_ACTION,
value: LOGIN_SUCCESS,
};
}
else {
return {
type: LOGIN_ACTION,
value: LOGIN_FAILURE,
};
}
};
export var logout_action = () => {
return {
type: LOGOUT_ACTION,
}
};
Reducers :
/* reducers/login.js */
import {LOGIN_ACTION, LOGOUT_ACTION, LOGIN_SUCCESS, LOGIN_FAILURE} from '../actions/actionTypes'
let cloneObject = (obj) => {
if(obj)
return JSON.parse(JSON.stringify(obj));
else
return {};
}
const initialState = {
user: {
loggedIn: false,
},
};
const auth = (state = initialState, action = {}) => {
switch(action.type) {
case LOGIN_ACTION: {
if(action.value === LOGIN_SUCCESS) {
return {
...state,
user: {
loggedIn: true
}
};
}else {
return {
...state,
user: {
loggedIn: false
}
};
}
}
case LOGOUT_ACTION: {
if(action.value === LOGIN_SUCCESS) {
return {
...state,
user: {
loggedIn: false
}
};
}else {
return state;
}
}
default: {
return state || initialState;
}
}
}
export default auth;
/* reducers/index.js */
import { combineReducers } from 'redux';
import auth from './login';
export {
auth,
};
Change onPress={this.onLoginPress} to onPress={this.onLoginPress.bind(this}.
Do the same for onPress={this.onLogoutPress} also.

Categories