How to delete items in array redux store? - javascript

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;

Related

React - mapStateToProps - "state is undefined"

I have the following problem: Using the code below I get the error:
this.props.posts is undefined
As I am following the tutorial https://codeburst.io/redux-a-crud-example-abb834d763c9 an I typed everything correct I am totally confused already at the beginning of my React career. Could you please help me?
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Post from './Post';
class AllPost extends Component {
render() {
return (
<div>
<h1>All Posts</h1>
{this.props.posts.map((post) => <Post key={post.id} post={post} />)}
</div>
);
}
}
const mapStateToProps = (state) => {
return {
posts: state,
}
}
export default connect(mapStateToProps)(AllPost);
Thanks a lot for your efforts!
The following is the postReducer:
const postReducer = (state = [], action) => {
switch(action.type) {
case 'ADD_POST':
return state.concat([action.data]);
default:
return state;
}
}
export default postReducer;
And here the index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import postReducer from './reducers/postReducer';
const store = createStore(postReducer);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>, document.getElementById('root'));
You need to declare an initial state. So your this.props.posts won't be undefined.
const initialState = {
posts: []
}
const postReducer = (state = initialState, action) => {
switch(action.type) {
case 'ADD_POST':
return { ...state, posts: [...state.posts, action.data]}
default:
return state;
}
}
export default postReducer;
The second error is located inside your mapStateToProps method. You need to access to posts redux state key. posts: state.posts like I did below
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Post from './Post';
class AllPost extends Component {
render() {
return (
<div>
<h1>All Posts</h1>
{this.props.posts.map((post) => <Post key={post.id} post={post} />)}
</div>
);
}
}
const mapStateToProps = (state) => {
return {
posts: state.posts, // you need to access to posts key
}
}
export default connect(mapStateToProps)(AllPost);

Uncaught (in promise) TypeError: Cannot read property 'map' of undefined

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

Cannot read property 'type' of undefined - redux

I'm trying to dispatch an action, but it returns "type" of undefined. I suspect Redux Thunk is not working properly.
Before I was dispatching the same action from the parent component and it was working.
Entry point
import React, { Component } from 'react'
import { Provider } from 'react-redux'
import configureStore from '../ConfigureStore'
import '../App.css';
import App from './theapp/theAppContainer';
const store = configureStore()
class Root extends Component {
render() {
return (
<Provider store={store}>
<App />
</Provider>
)
}
}
export default Root;
Store
import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import { createLogger } from 'redux-logger'
import allReducers from './reducers/index'
const loggerMiddleware = createLogger()
export default function configureStore() {
return createStore(
allReducers,
applyMiddleware(thunkMiddleware, loggerMiddleware)
)
}
The app - routing. Before I was dispatching the action at this level and it was working.
import React, { Component } from 'react'
import Cards from '../templates/cards/CardsContainer'
import EditApp from '../pages/editApp/EditApp'
import NewApp from '../pages/NewApp'
import AppReport from '../pages/AppReport'
import { Route, Switch, HashRouter } from 'react-router-dom'
export default class TheApp extends Component {
constructor(props) {
super(props)
}
render() {
const appId = window.location.href.split('id=')[1];
return (
<HashRouter>
<Switch>
<Route exact path="/" component={Cards} />
<Route path="/app" component={EditApp} />
<Route exact path="/new" component={NewApp} />
<Route path="/report" component={AppReport} />
</Switch>
</HashRouter>
)
}
}
The container where I dispatch the action
import { connect } from 'react-redux'
import Cards from './Cards'
import {
fetchAppsData
} from '../../../actions'
function mapStateToProps(state){
return {
apps: state.apps
}
}
function matchDispatchToProps(dispatch){
return dispatch(fetchAppsData)
}
export default connect(mapStateToProps, matchDispatchToProps)(Cards)
Action
import fetch from 'cross-fetch'
import * as helpers from '../Helpers';
export const REQUEST_ITEMS = 'REQUEST_ITEMS'
export const RECEIVE_ITEMS = 'RECEIVE_ITEMS'
export function fetchAppsData() {
return (dispatch) => {
return dispatch(fetchItems())
}
}
function fetchItems() {
return dispatch => {
dispatch(requestItems())
return fetch(helpers.appData)
.then(response => response.json())
.then(json => dispatch(receiveItems(json)))
}
}
function requestItems() {
return {
type: REQUEST_ITEMS
}
}
function receiveItems(json) {
return {
type: RECEIVE_ITEMS,
items: json,
receivedAt: Date.now()
}
}
The reducer
import {
REQUEST_ITEMS,
RECEIVE_ITEMS
} from '../actions/apps-actions'
export default function apps(
state = {
isFetching: false,
items: []
},
action
) {
switch (action.type) {
case REQUEST_ITEMS:
return Object.assign({}, state, {
isFetching: true
})
case RECEIVE_ITEMS:
return Object.assign({}, state, {
isFetching: false,
items: action.items
})
default:
return state
}
}
Try changing
function matchDispatchToProps(dispatch){
return dispatch(fetchAppsData)
}
Into this:
function matchDispatchToProps(dispatch){
return {
fetchAppsData: () => dispatch(fetchAppsData())
}
}
Also the function should be called “mapDispatchToProps” but that is not important for your problem.
I believe calling
dispatch(fetchAppsData)
isn't correct, fetchAppsData is a thunk creator, not a thunk directly. Instead you would want to do
dispatch(fetchAppsData())

Why my <Cities /> component in ReactJS project do not see any props?

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 am not sure why redux isn't recognizing thunk

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
});
};

Categories