React Redux ->How can I map over my state? - javascript

So I am making a to-do list in React in order to learn redux and I've been wondering how can I use something like the map function to map over the state, so that I can show the data stored within in different divs?
here's my initialState:
const tasks=
[
]
And then there's my reducer:
const taskReducer = (state=tasks,action) =>
{
switch(action.type){
case 'addTask':
return[
...state,
{
id: nextToDo+=1,
text: action.text,
completed: false
}
]
default:
return state;
}
}
What I want to do is something among the lines of:
{tasks.map(task=>
<div>
<h1>{task.text}</h1>
<div>)}
But it doesn't really work, what are some ways I can accomplish this?

You also use redux connect() method.
You can export default connect(mapStatetoProps)
for moreInfo:https://react-redux.js.org/api/connect

I found the solution people, here's the deal, I had to use mapStateToProps. I also had to change from functional to class component. So basically I first split my app in seperate files, one for the reducers and one for the store, here are all my files:
App.js:
import React from 'react';
import './App.css';
import tasksApp from './tasksApp';
import {Provider} from 'react-redux'
import store from './store'
function App() {
return (
<div>
<Provider store={store}>
<tasksApp></tasksApp>
</Provider>
</div>
);
}
export default App;
TasksApp.js:
import React, {Component} from 'react'
import 'bootstrap/dist/css/bootstrap.min.css'
import {Button} from 'react-bootstrap'
import {connect} from 'react-redux'
import $ from 'jquery'
import store from './store'
class tasksApp extends Component {
render(){
console.log(this.props)
const {tasks} = this.props
let nextToDo = 0;
const addTask=()=>
{
store.dispatch({
type: 'addTask',
text: $('.form-control').val()
})
}
return (
<div>
<h1>Enter Task</h1>
<input className='form-control' placeholder='Enter task'></input>
<Button variant='success' onClick={()=>addTask()}>Add Task</Button>
{tasks.map(task=>
<div key={task.id}>
<h1>{task.text}</h1>
<h2>{task.id}</h2>
<h3>{task.completed}</h3>
</div>)}
</div>
)
}
}
const mapStateToProps=(state)=>
{
return{
tasks: state
}
}
export default connect(mapStateToProps)(tasksApp)
store.js:
import {createStore} from 'redux'
import taskReducer from './reducers'
const store = createStore(taskReducer)
store.subscribe(()=>
console.log('Your store is now', store.getState())
)
export default store
reducers.js:
import store from './store'
import $ from 'jquery'
let nextToDo = 0;
const tasks=
[
{
id: nextToDo+=1,
text: 'action.text',
completed: false
}
]
const taskReducer = (state=tasks,action) =>
{
switch(action.type){
case 'addTask':
return[
...state,
{
id: nextToDo+=1,
text: $('.form-control').val(),
completed: false
}
]
default:
return state;
}
}
export default taskReducer;

Related

React Redux -> Map is not a function?

So I am learning how to use redux and redux persist and currently I stuck at a problem right now. Whenever I try to map my store's content, it throws an error saying TypeError: tasks.map is not a function and I don't really know why the problem is occuring. I've googled around and tried debugging it, also tried to re-write the code a couple of time but it was all to no avail. Here's my entire code:
rootReducer.js
import React from 'react'
let nextToDo = 0;
const task=[
{
}
]
const reducer =(state=task, action)=>
{
switch(action.type)
{
case 'add':
return[
...state,
{
name: 'new',
id: nextToDo+=1
}
]
default:
return state;
}
}
export default reducer
store.js
import reducer from './rootReducer'
import {applyMiddleware,createStore} from 'redux'
import logger from 'redux-logger'
import {persistStore, persistReducer} from 'redux-persist'
import storage from 'redux-persist/lib/storage'
const persistConfig ={
key: 'root',
storage
}
export const persistedReducer = persistReducer(persistConfig, reducer)
export const store = createStore(persistedReducer, applyMiddleware(logger));
export const persistor = persistStore(store);
export default {store, persistor}
Index.js:
import React, {Component} from 'react'
import {createStore} from 'redux'
import reducer from './rootReducer'
import 'bootstrap/dist/css/bootstrap.min.css'
import {Button} from 'react-bootstrap'
import {store} from './store'
import {connect} from 'react-redux'
class Index extends Component {
render(){
const {tasks} = this.props
const add=()=>
{
store.dispatch(
{
type: 'add',
}
)
}
store.subscribe(()=>console.log('your store is now', store.getState()))
return (
<div>
{tasks.map(task=><div>{task.name}</div>)}
<Button onClick={()=>add()}></Button>
</div>
)
}
}
const mapStateToProps=(state)=>
{
return{
tasks: state
}
}
export default connect(mapStateToProps)(Index)
Try to declare state this way:
state = {
tasks: [{}]
}
Then, on Index.js, you can pass it to props by doing this:
const mapStateToProps=(state)=>
{
return {
tasks: state.tasks
}
}
And use it inside the Component with props.tasks

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

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.

How to delete items in array redux store?

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;

Categories