Being a newbie to react native ,I am finding it difficult to connect my redux with react native and make it work. After javascript bundle finishes ,I see an error "can't read property type of undefined" or "could not find store in either the context or props of "connect".Either wrap the root component in a or explicitly pass "store" as prop.I don't see any of the console.log working except for reducer .
Here is the action that I am using
import {ADD_PLACE,DELETE_PLACE,DESELECT_PLACE,SELECT_PLACE} from './actiontypes';
export const addPLace =(placeName) =>{
console.log('addPLace is being dispatched now');
console.log('In addPLace reducer');
return{
type:ADD_PLACE,
payload:{
placeName:placeName
}
};
};
export const deletePlace =()=>{
return{
type:DELETE_PLACE
};
}
export const selectedPlace =(key) =>{
return{
type:SELECT_PLACE,
payload:{
placekey:key
}
};
};
export const deselectPlace =()=>{
return {
type:DESELECT_PLACE
};
};
Here is the reducer part
import {ADD_PLACE,DELETE_PLACE,SELECT_PLACE,DESELECT_PLACE} from '../actions/actiontypes';
import PlaceImage from "../../../src/assets/download.jpeg";
const INITIAL_STATE={
places:[],
selectedPlace:null
}
const reducer =(action,state=INITIAL_STATE) =>{
console.log('INside reducer');
console.log(action);
switch(action.type){
case ADD_PLACE:
return {
...state,
places:state.places.concat({
key:Math.random(),
name:action.payload.placeName,
image:placeImage
})
};
case DELETE_PLACE:
return{
...state,
places:state.places.filter(place =>{
return place.key !== state.selectedPlace.key;
}),
selectPlace:null
};
case SELECT_PLACE:
return{
...state,
selectedPlace:state.places.find(place=>{
return place.key ===action.payload.placekey;
})
};
case DESELECT_PLACE:
return{
...state,
selectPlace:null
};
default:
return state;
}
}
export default reducer;
Here is the App.js
import React, { Component } from "react";
//import { StyleSheet, Text, View, TextInput, Button } from "react-native";
import store from './src/store/reducers/index.js';
import {Provider} from 'react-redux';
//import {createStore} from 'redux';
//import {connect} from 'react-redux';
import Home from './Home.js';
export default class App extends React.Component {
render() {
console.log('inside App');
console.log(store);
return (
<Provider store={store}>
<Home />
</Provider>
);
}
}
Here is the Home.js
import React, { Component } from "react";
import { StyleSheet, Text, View, TextInput, Button } from "react-native";
//import ListItem from './src/components/ListItem';
import PlaceInput from "./src/components/PlaceInput";
import PlaceList from "./src/components/PlaceList";
//import PlaceImage from "./src/assets/download.jpeg";
import PlaceDetail from "./src/components/PlaceDetail";
//import configureStore from './src/store/reducers/index.js';
//import {Provider} from 'react-redux';
//import {createStore} from 'redux';
import {connect} from 'react-redux';
import {addPLace,deletePlace,selectedPlace,deselectPlace} from './src/store/actions';
//const store=configureStore();
class Home extends React.Component {
placeAddedHandler =val=>{
console.log('Val is ',val);
console.log(val);
this.props.onAddPlace(val);
};
placeSelectHandler =id=>{
console.log('id is');
this.props.onSelectPlace(id);
};
placeDeleteHandler =() =>{
console.log('inside delete handler');
this.props.onDeletePlace();
};
modelClosedHandler =() =>{
console.log('iinside close handler');
this.props.onDeslectPlace();
}
render() {
console.log('Inside render function');
return (
<View style={styles.container}>
<PlaceInput onPlaceAdded={this.placeAddedHandler}/>
<PlaceList places={this.props.places} onItemSelected={this.placeSelectHandler}/>
<PlaceDetail
selectedPlace={this.props.selectedPlace}
onItemDeleted={this.placeDeleteHandler}
onModalClosed={this.modelClosedHandler}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding:30,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'flex-start',
},
});
const mapStateToProps=state => {
console.log('Inside mapStateToProps ');
console.log(state );
return {
places:state.places.places,
selectedPlace:state.places.selectPlace
};
}
const mapDispatchToProps = dispatch =>{
return {
onAddPlace:(name)=>dispatch(addPLace(name)),
onDeletePlace:()=>dispatch(deletePlace()),
onSelectPlace:(id)=>dispatch(selectedPlace(id)),
onDeslectPlace:()=>dispatch(deselectPlace())
};
}
export default connect(mapStateToProps,mapDispatchToProps)(Home);
Link to github repo of project at this moment
github link
Looks like you have made a small import/export error.
In your reducers/index.js you are exporting it as a non default value which you are trying to import as default value in App.js.
import store from './src/store/reducers/index.js';
should be
import {store} from './src/store/reducers/index.js';
Let me know if it works.
Related
i am trying to include my common component in my main.js
this one I did it it successfully.
but in my common component, I am trying to print my redux data values.
so I created a method called handleClickForRedux to print the values.
I have included mapStateToProps and mapDispatchToProps
but still value is not printing at this line. console.log("event reddux props--->", props);
can you tell me how to fix it.
providing my code snippet and sandbox below.
https://codesandbox.io/s/react-redux-example-265sd
scroll.js
import React, { useEffect, useState, Fragment } from "react";
import PropTypes from "prop-types";
import { withStyles } from "#material-ui/core/styles";
import Card from "#material-ui/core/Card";
//import CardActions from "#material-ui/core/CardActions";
import CardContent from "#material-ui/core/CardContent";
import Typography from "#material-ui/core/Typography";
import Drawer from "#material-ui/core/Drawer";
import { bindActionCreators } from "redux";
import * as actionCreators from "../actions/actionCreators";
import { connect } from "react-redux";
import { compose } from "redux";
function SportsMouse(classes, props) {
// const [canEdit, setCanEdit] = useState(false);
function handleClickForRedux(event) {
console.log("event--->", event);
console.log("event reddux props--->", props);
}
return (
<Card>
<div onClick={handleClickForRedux}>I am here </div>
</Card>
);
}
SportsMouse.propTypes = {
classes: PropTypes.object.isRequired
};
function mapStateToProps(state) {
return {
posts: state.posts,
comments: state.comments
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(actionCreators, dispatch);
}
export default compose(
connect(
mapStateToProps,
mapDispatchToProps
)
)(SportsMouse);
main.js
import React from "react";
import { Link } from "react-router-dom";
import Scroll from "../commonComponents/scroll";
const Main = props => {
const { children, match, ...rest } = props;
return (
<div>
<h1>
<Scroll />
<Link to="/">Reduxstagram</Link>
</h1>
{React.Children.map(children, child => React.cloneElement(child, rest))}
</div>
);
};
export default Main;
Even when using material-ui, components only accept one argument. classes exists inside props. If you console.log(classes) you'll see that it contains all of your props, including material-ui's styles. It should be this:
function SportsMouse(props) {
So, when I am trying to access my news props to display news title to my page I am receiving and error like this one:
Error Msg
import React, { Component } from 'react';
import Search from './Search';
import { connect } from 'react-redux';
import NewsItem from './NewsItem';
class NewsResults extends Component {
render() {
return (
<div>
<Search />
{this.props.news.map(item => {
return <NewsItem new={item} key={item.objectID} showButton={true}/>
})
}
</div>
)
}
}
function mapStateToProps(state) {
console.log(state)
return {
news: state.news
}
}
export default connect(mapStateToProps, null)(NewsResults);
NewsItem.js is just a component through which I will display the results on my application.
import React, { Component } from 'react';
class NewsItem extends Component {
render(){
return(
<div className="col-sm-12 col-sm-3">
<div className="thumbnail">
<div className="caption">
<h3>{this.props.new.title}</h3>
</div>
</div>
</div>
)
}
}
export default NewsItem;
This is where I'm fetching my information from an api and then I want to display on my page using maps
class Search extends Component {
constructor(props) {
super(props);
this.state = {
query: ''
};
}
search(){
console.log('Search button clicked', this.state.query);
let url = `http://hn.algolia.com/api/v1/search_by_date?query=${this.state.query}`;
// console.log(url);
fetch(url, {
method: 'GET'
}).then(response=> response.json())
.then(jsonObject => {this.props.news(jsonObject.results)});
}
This is my redux action code in action.js file
export const NEWS = "NEWS";
export function news(items) {
const action = {
type: NEWS,
items
}
return action;
}
This is the reducer file
import { NEWS } from '../actions';
const initialState = {
news: []
}
export default function (state= initialState, action) {
switch(action.type) {
case NEWS:
console.log("News are ",action.items);
return {
...state,
news: action.items
};
default:
return state;
}
};
So now I have changed my reducer to be in 2 seperate files I will post below. Also by doing that error message changed to this:
This is the new Error I am getting now
My reducer files are below:
import { NEWS } from '../actions';
export default function news(state = [], action) {
switch(action.type) {
case NEWS:
console.log("News are ",action.items);
return action.items;
default:
return state;
}
}
Second Reducer File:
import news from './news_reducer';
import { combineReducers } from 'redux';
const rootReducer = combineReducers({
news
});
export default rootReducer;
Then I am importing my rootReducer from reducer folder in index.js outside of source folder where my redux store is.
This is how I am creating my store in index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App';
import registerServiceWorker from './registerServiceWorker';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './reducers';
const store = createStore(rootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
, document.getElementById('root'));
registerServiceWorker();
Now, My problem is that I am trying to send data from actions but reducer isn't recieving it for some reason.
Another Error popped up now. Another Error
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
});
};
Im newbie at Redux and Redux, so im trying get a simple todo list.
I've got array in the store. Its okay with adding, but when im deleting item see this:
TypeError: Cannot read property 'map' of undefined
at
var items =this.props.tasks.map((item,i) => (this.props.deleteTask(item)} />));
in ListTODO.js
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducer from './reducer';
const store = createStore(reducer);
ReactDOM.render(
<Provider store={store}>
<App className="container" />
</Provider>,
document.getElementById('root'));
registerServiceWorker();
App.js
import React, { Component } from 'react';
import InputTask from './InputTask';
import ListTODO from './ListTODO';
import { connect } from 'react-redux';
class App extends Component {
render() {
return (<div>
<strong>TODO LIST</strong>
<InputTask addTask={this.props.addTask} /><br />
<ListTODO tasks={this.props.store} deleteTask={this.props.deleteTask} />
</div>);
}
}
const mapStateToProps = state => {
return {
store: state
}
}
const mapDispatchToProps = dispatch => {
return {
addTask: (task) => {
dispatch({ type: 'UPDATE_LIST', payload: task })
},
deleteTask: (task) => {
dispatch({ type: 'DELETE_TASK', payload: task })
}
}
}
export default connect(
mapStateToProps,
mapDispatchToProps)
(App);
reducer.js
const initialState = ["task1", "task2"];
export default function todoList(state = initialState, action) {
switch (action.type) {
case 'UPDATE_LIST':
return [
...state,
action.payload
];
case 'DELETE_TASK':
console.log("DELETING", (action.payload))
return
state.filter(element => element !== action.payload);
default: return state;
}
}
ListTODO.js
import React, { Component } from 'react';
import TodoItem from './TodoItem';
import { connect } from 'react-redux';
class ListTODO extends Component {
constructor() {
super();
}
render() {
console.log("LIST TODO:"+ this.props.tasks);
var items =this.props.tasks.map((item,i) => (<TodoItem item={item} key={i} deleteTask={(item)=>this.props.deleteTask(item)} />));
return (
<ul>
{items}
</ul>
);
}
}
export default ListTODO;