I'm unable to delete the todo data one by one - javascript

I created a todo app, and now I'm trying to delete the todo data one by one, but I'm getting the error stating that TypeError: Cannot read properties of undefined (reading 'id'). Don't know what to do next. I'm using the vuex concept and just help me to clear the error.
App.vue:
<template>
<div>
<input type="text" v-model="title">
<button #click="onSubmit">submit</button>
<div v-for="datas in allData" :key="datas.id">
<h1>{{datas.title}}</h1>
<i class="fas fa-trash-alt" #:click="deleteData(todo.id)"></i>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
export default {
data() {
return {
title: ''
}
},
methods: {
...mapActions(['fetchData', 'newData', 'deleteData']),
onSubmit(e) {
e.preventDefault();
this.newData(this.title)
},
},
computed: mapGetters(['allData']),
created() {
this.fetchData();
}
}
</script>
index.js (store);
import axios from 'axios'
import { createStore } from 'vuex'
export default createStore({
state: {
todos: [],
},
getters: {
allData: (state) => {
return state.todos
}
},
mutations: {
setData: (state, todoData) => (state.todos = todoData),
new: (state, todo) => (state.todos.unshift(todo)),
removeData: (state, id) => state.todos = state.todos.filter((todo) => todo.id !== id),
},
actions: {
async fetchData({ commit }) {
const response = await axios.get('https://jsonplaceholder.typicode.com/todos')
commit('setData', response.data)
},
async newData({ commit }, title) {
const response = await axios.post('https://jsonplaceholder.typicode.com/todos', { title, completed: false })
commit('new', response.data)
},
async deleteData({ commit }, id) {
await axios.delete(`https://jsonplaceholder.typicode.com/todos/${id}`);
commit('removeData', id)
}
}
})

In the template, you iterate through array and passing todo.id to delete function, why not extracted item from v-for loop dates.id?
<template>
<div>
<input type="text" v-model="title">
<button #click="onSubmit">submit</button>
<div v-for="item of data" :key="item.id">
<h1>{{item.title}}</h1>
<i class="fas fa-trash-alt" #:click="deleteData(item.id)"></i>
</div>
</div>
</template>
And remove s in your data name because you extract one item, not items from loop.

Related

why is my pinia still showing undefined and how can i make my app wait till pinia has loaded before filtering the producst by ID

so here is my vue sfc that is supposed to display a list of products that are sold by a given brand ID, for some reason when i fetch the products and filter them by the brand.id the products array is still undefined
<script setup>
import { useRoute } from 'vue-router'
import { ref, computed } from "vue";
import axios from 'axios'
import { useProductsStore } from "../stores/products";
const store = useProductsStore();
const baseURL = "http://127.0.0.1:8000/"
const route = useRoute()
const id = route.params.id
store.fetchProducts()
const getProductsById = store.getProductsByBrandId
</script>
<template>
<div class="brandDetails">
<div>
<h2>Brand Details</h2>
ID: {{ id }}
</div>
<div>
<h2>Products</h2>
<p v-for="product in getProductsById(id)">{{ product.name }}</p>
</div>
</div>
</template>
and here is my pinia store.js
import { defineStore } from "pinia";
import axios from "axios";
export const useProductsStore = defineStore("products", {
state: () => {
return {
products: [],
vendors: [],
brands: [],
};
},
getters: {
getProducts: (state) => {
return state.products;
},
getVendors: (state) => {
return state.vendors;
},
getBrands: (state) => {
return state.brands;
},
getProductsByBrandId: (state) => {
return (id) => state.products.filter((x) => x.brand.id === id);
},
},
actions: {
async fetchProducts() {
try {
const data = await axios.get("http://127.0.0.1:8000/products.json");
this.products = data.data;
} catch (error) {
alert(error);
console.log(error);
}
},
async fetchVendors() {
try {
const data = await axios.get("http://127.0.0.1:8000/vendors.json");
this.vendors = data.data;
} catch (error) {
alert(error);
console.log(error);
}
},
async fetchBrands() {
try {
const data = await axios.get("http://127.0.0.1:8000/brands.json");
this.brands = data.data;
} catch (error) {
alert(error);
console.log(error);
}
},
},
});
i am not sure what i am doing wrong but i think the problem is that its trying to filter an array which is not yet defined. if so, how can i make sure its defined before filtering it, or maybe there a much better way to do this and im just trippin
any help is appreciated
So here's how I got it working
gonna post it here in case anyone else got stuck on the same thing I did
could be this is something really basic and I should've known, but here it is anyway
brandDetail.vue
<script setup>
import { useRoute } from 'vue-router'
import { ref, reactive } from "vue";
import axios from 'axios'
import { useProductsStore } from "../stores/products";
import Card from 'primevue/card';
const store = useProductsStore();
const baseURL = "http://127.0.0.1:8000/"
const route = useRoute()
const brandId = route.params.id
// get brand details
const brandDeets = ref({
id: "loading",
name: "Loading"
})
async function getBrandDeets(id) {
const link = baseURL + "brands/" + id
try {
const data = await axios.get(link)
brandDeets.value = data.data;
} catch (error) {
console.log(error);
}
};
getBrandDeets(brandId)
// filter producst by brandID
let filteredProducts = reactive([]);
store.fetchProducts()
.then(() => {
const prods = store.products.filter(x => x.brand.id == brandId)
filteredProducts.push(prods)
})
</script>
<template>
<div class="branddetails">
<button #click="$router.go(-1)">Back</button>
<div>
<h1>Brand Details</h1>
<hr>
<h3>Brand Name: {{ brandDeets.name }}</h3>
<p>ID: {{ brandId }}</p>
<br>
</div>
<div>
<h2>{{ brandDeets.name }} Products</h2>
<hr>
<div v-if="!filteredProducts[0].length == 0" class="productCardCont">
<Card v-for="product in filteredProducts[0]" class="productCard">
<template #title>{{ product.name }}</template>
<template #content>
<p>SKU: <router-link :to="'/catalog/' + product.id">{{ product.sku }}</router-link></p>
<p>Description: {{ product.description }}</p>
</template>
</Card>
</div>
<p v-else>No Products Found</p>
</div>
</div>
</template>
Major thanks to everyone who helped me out!

Why line number doesn't work when click on another page?

I use vue js version 2.6.11
I have 3 component vue
My first component like this :
<template>
...
<page-listing
:lastPage="lastPage"
:perPage="perPage"
:changePage="changePage"
></page-listing>
</template>
...
</template>
<script>
import { mapActions, mapGetters } from "vuex";
import PageListing from "#/views/app/report/PageListing";
export default {
components: {
"page-listing": PageListing
},
methods: {
...mapActions([
"getReport",
"setPageAction",
]),
searchChange() {
this.loadPage()
},
async changePage(pageNum) {
await this.setPageAction(pageNum)
this.loadPage();
},
loadPage(){
const page = this.page
this.getReport({page});
},
},
computed: {
...mapGetters({
perPage: "reportPerpage",
lastPage: "reportLastPage",
page: "reportPage",
}),
},
mounted() {
this.loadPage();
}
};
</script>
My second component like this :
<template>
...
<div class="card-body">
<p class="mb-0 w-5 w-sm-100">Number</p>
<div class="w-30 w-sm-100">Description</div>
<div class="w-20 w-sm-100">Date</div>
<div class="w-10 w-sm-100">Modified By</div>
</div>
...
<b-row key="list">
<b-colxx xxs="12" v-for="(item,index) in itemsWithLineNumber" :key="index" :id="item.id">
<list-item
:key="item.id"
:data="item"
/>
</b-colxx>
</b-row>
<b-row v-if="lastPage>1">
...
<b-pagination-nav
:number-of-pages="lastPage"
:link-gen="linkGen"
:value="page"
#change="(a)=>changePage(a)"
:per-page="perPage"
align="center"
use-router
>
...
</b-row>
...
</template>
<script>
import { mapActions, mapGetters } from "vuex";
import ListItem from "./ListItem";
export default {
components: {
"list-item": ListItem
},
props: [
"lastPage",
"changePage",
],
methods: {
...mapActions(["setItemsAction"]),
linkGen(pageNum) {
return pageNum === 1 ? '?' : `?page=${pageNum}`
},
},
computed: {
...mapGetters({
perPage: "reportPerpage",
page: "reportPage",
items: "reportItems",
}),
filtered() {
const start = this.page * this.perPage - this.perPage
return this.items.slice(start, start + this.perPage)
},
itemsWithLineNumber() {
return this.filtered.map((item, idx) => {
return {...item, lineNumber: (this.page - 1) * this.perPage + idx + 1}
})
}
}
};
</script>
My three component like this :
<template>
<b-card no-body>
<div class="pl-2 d-flex">
<div class="card-body">
<p class="mb-0 text-muted w-5">{{data.lineNumber}}</p>
<p class="mb-0 text-muted w-30">{{data.description}}</p>
<p class="mb-0 text-muted w-20">{{data.date}}</p>
<p class="mb-0 text-muted w-10">{{data.created_by}}</p>
</div>
</div>
</b-card>
</template>
<script>
export default {
props: ['data'],
}
</script>
My vuex store like this :
const state = {
items: null,
reportError: '',
reportSuccess: '',
page: 1,
perPage: 4,
lastPage: 0,
}
const getters = {
reportError: state => state.reportError,
reportSuccess: state => state.reportSuccess,
reportItems: state => state.items,
reportPage: state => state.page,
reportPerpage: state => state.perPage,
reportLastPage: state => state.lastPage,
}
const mutations = {
getReportSuccess (state, res) {
state.items = res.data
state.perPage = res.meta.per_page;
state.lastPage = res.meta.last_page;
},
getReportError (state, error) {
state.items = null
},
setReportPage (state, payload) {
state.page = payload
},
setPageMutation (state, payload) {
state.page = payload
},
setItemsMutation (state, payload) {
state.items = payload
},
}
const actions = {
getReport ({ commit }, payload) {
...
axios
.get(`${api}/report/list`, { params })
.then(r => r.data)
.then(res => {
if (res.data) {
commit('getReportSuccess', res.data)
} else {
commit('getReportError', 'error:getReport')
}
})
},
setReportPage ({ commit }, payload) {
commit('setReportPage', payload)
},
setPageAction({ commit}, payload) {
commit('setPageMutation', payload)
},
setItemsAction({ commit}, payload) {
commit('setItemsMutation', payload)
},
}
export default {
state,
getters,
mutations,
actions,
}
When the page loads the first time, the line number works and appears. But when I click on the page 2, the page displays blank data
How can I solve this problem?
Please help. Thanks
Update :
Demo like this : https://codesandbox.io/s/prod-hooks-dzk07b
Your problem is with the filtered
filtered() {
const start = this.currentPage * this.perPage - this.perPage;
return this.items.slice(start, start + this.perPage);
},
the items response only has the first n results, when you get rid of them using filter, the array is empty.
you can remove the function and use items result instead
itemsWithLineNumber() {
return this.items.map((item, idx) => {
return {
...item,
lineNumber: (this.currentPage - 1) * this.perPage + idx + 1,
};
});
},

I need to learn vuex in short time because and i cant figure out how to migrate my vue js to vuex?

This is my github page and you can see what i have done in the help branch: https://github.com/maltin1234/blog
I need to change the code in the components but i dont know how.
CreateComponent.vue
<template>
<div>
<h1>Create A Post</h1>
<form #submit.prevent="addPost">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Post Title:</label>
<input type="text" class="form-control" v-model="post.title" />
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Post Body:</label>
<textarea
class="form-control"
v-model="post.body"
rows="5"
></textarea>
</div>
</div>
</div>
<br />
<div class="form-group">
<button class="btn btn-primary">Create</button>
</div>
</form>
</div>
</template>
export default {
<script>
export default {
name: "CreateComponent",
data() {
return {
title: "",
};
},
methods: {
...mapActions(["addPost"]),
onSubmit(e) {
e.preventDefault();
this.addPost(this.title);
},
},
};
</script>
I have a node js backend and i want my vuex to fetch those endpoints. The node js backend consists of a mongodb connection and a model with articles. This is my try with vuex.
post.js (vue.js project)
import axios from "axios";
const state = {
posts: [],
};
const getters = {
allPosts: (state) => state.Posts,
};
const actions = {
//an action: makes a request, gets a response and calls a mutation
async fetchPosts({ commit }) {
// commit - to call the mutation
const response = await axios.get("http://localhost:4000/posts");
commit("setPosts", response.data);
},
async addPosts({ commit }, title) {
const response = await axios.post("", { title, completed: false });
commit("newPost", response.data);
},
async deletePosts({ commit }, id) {
await axios.delete(`http://localhost:4000/posts/delete/${id}`);
commit("removePosts", id);
},
async filterPosts({ commit }, e) {
//Get selected number
// const limit = parseInt(e.target.options[e.target.options.selectedIndex].innerText);
const limit = e.target.value;
const response = await axios.get(`http://localhost:4000/posts`);
commit("setPosts", response.data);
},
async updatePosts({ commit }, updatePosts) {
const response = await axios.put(
`http://localhost:4000/posts/update/${this.$route.params.id}`,
updatePosts
);
console.log(response.data);
commit("updatePosts", response.data);
},
};
const mutations = {
setPosts: (state, Posts) => (state.posts = posts),
newPosts: (state, posts) => state.posts.unshift(posts),
removePosts: (state, id) =>
(state.posts = state.posts.filter((posts) => posts.id !== id)),
updatePosts: (state, updTodo) => {
const index = state.Posts.findIndex((posts) => posts.id === updPosts.id);
if (index !== -1) {
state.posts.splice(index, 1, updPosts);
}
},
};
export default {
state,
getters,
actions,
mutations,
};
store.js
import Vuex from "vuex";
import Vue from "vue";
import todos from "./modules/todos";
//load Vuex
Vue.use(Vuex)
//create store
export default new Vuex.Store({
modules: {
posts
}
})
Node project (https://github.com/maltin1234/blognode)
Firstly for using Vuex you have create your store and add it into your project, then for using any actions/state/getters/setters you have to import them into your component via vuex methods, for instance:
import { mapActions, mapState } from 'vuex'
export default {
computed: {
...mapState('yourModule', ['stateValueOne', 'stateValueTwo'])
},
methods: {
...mapAction('yourModule', ['actionOne', 'actionTwo'])
}
}
Then you can get them by this identifier
Simply check Vuex API Reference, It's pretty simple
I changed the name from index.js to store.js
store.js
import Vuex from "vuex";
import Vue from "vue";
import store from "./post";
//load Vuex
Vue.use(Vuex);
//create store
export default new Vuex.Store({
modules: {
posts,
},
});
Then i wasnt sure exactly how you meant dima but I changed my CreateComponent to this code.
CreateComponent.js
<template>
<div>
<h1>Create A Post</h1>
<form #submit.prevent="addPost">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Post Title:</label>
<input type="text" class="form-control" v-model="post.title" />
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Post Body:</label>
<textarea
class="form-control"
v-model="post.body"
rows="5"
></textarea>
</div>
</div>
</div>
<br />
<div class="form-group">
<button class="btn btn-primary">Create</button>
</div>
</form>
</div>
</template>
export default {
<script>
export default {
name: "AddPost",
data() {
return {
title: "",
};
},
methods: {
...mapActions(["addPost"]),
onSubmit(e) {
e.preventDefault();
this.addPosts(this.title);
},
},
};
</script>
And this is my post.js that does the requests to my backend
// here should be added: state, getters, actions, mutations
import axios from "axios";
const state = {
posts: [],
};
const getters = {
allPosts: (state) => state.Posts,
};
const actions = {
//an action: makes a request, gets a response and calls a mutation
async fetchPosts({ commit }) {
// commit - to call the mutation
const response = await axios.get("http://localhost:4000/posts");
commit("setPosts", response.data);
},
async addPosts({ commit }, title) {
const response = await axios.post("http://localhost:4000/posts/add", {
title,
completed: false,
});
commit("newPost", response.data);
},
async deletePosts({ commit }, id) {
await axios.delete(`http://localhost:4000/posts/delete/${id}`);
commit("removePosts", id);
},
async filterPosts({ commit }, e) {
//Get selected number
// const limit = parseInt(e.target.options[e.target.options.selectedIndex].innerText);
const limit = e.target.value;
const response = await axios.get(`http://localhost:4000/posts`);
commit("setPosts", response.data);
},
async updatePosts({ commit }, updatePosts) {
const response = await axios.put(
`http://localhost:4000/posts/update/${this.$route.params.id}`,
updatePosts
);
console.log(response.data);
commit("updatePosts", response.data);
},
};
const mutations = {
setPosts: (state, posts) => (state.posts = posts),
newPosts: (state, posts) => state.posts.unshift(posts),
removePosts: (state, id) =>
(state.posts = state.posts.filter((posts) => posts.id !== id)),
updatePosts: (state, updPosts) => {
const index = state.Posts.findIndex((posts) => posts.id === updPosts.id);
if (index !== -1) {
state.posts.splice(index, 1, updPosts);
}
},
};
export default {
state,
getters,
actions,
mutations,
};
//this is a boilerplate for vuex module

Computed property is not defined on the instance but reference during render

Background:
I have a child component that receives an array called expenseButton as props. Within the array are objects with values which I am trying to get the sum of using array.reduce()
Problem
When I use methods to get the sum of the values it works perfectly fine but when I try to make it a computed property I get an error that states:
("test" is the name of the computed property)
Property or method "test" is not defined on the instance but referenced during render
<script>
export default {
props: {
expenseButton: Array,
},
data() {
return {
chosenExpenseId: null
};
},
computed: {
test() {
return this.expenseButton.reduce((acc, curr) => {
acc += curr.expensesValue;
return acc;
}, 0);
}
}
}
};
</script>
<template>
<div>
<div class="yourBalance">
Your monthly balance
<br />
<span>${{ test }}</span>
</div>
</div>
<template>
UPDATE
The "expenseValue" property within the "expenseButton" array is coming from a database on the backend using axios
Parent component
<template>
<div>
<expense-button :myExpense="myExpense" :expenseButton="expenseButton"></expense-button>
</div>
</template>
<script>
import Expenses from "../components/expenses.vue";
import axios from "axios";
export default {
components: {
"expense-button": Expenses
},
data() {
return {
budgetOwner: "",
myExpense: [],
expenseButton: [],
component: "",
errored: false
};
},
beforeRouteEnter(to, from, next) {
axios
.get("/api/budget", {
headers: { "Content-Type": "application/json" },
withCredentials: true
})
.then(res => {
next(vm => {
if (res.data.budget.length > 0) {
vm.myExpense = res.data.budget;
vm.expenseButton = res.data.budget[0].expenses;
}
});
})
.catch(err => {
next(vm => {
console.log(err.response);
vm.errored = true;
});
});
}
}
</script>
Data from database
"budget":[{"expenses":[
{"expensesKey":"a","expensesValue":1,"subExpenses":"","newValue":""},
{"expensesKey":"b","expensesValue":2,"subExpenses":"","newValue":""},
{"expensesKey":"c","expensesValue":3,"subExpenses":"","newValue":""}
]
Try this
test() {
if(this.expenseButton){
return this.expenseButton.reduce((acc, curr) => {
acc += curr.expensesValue;
return acc;
}, 0);
}
else{
return ''
}
}
Try to help you. The problem will be in curr.expensesValue. What is expensesValue? And one more question. Are you mount right your app? Are you have the same id in the root like a el:'#app' and div#id in my example?
new Vue({
el: "#app",
data:{
expenseButton:[1,2,3,4,5],
chosenExpenseId: null
},
computed: {
test() {
return this.expenseButton.reduce((acc, curr) => acc + curr)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="yourBalance">
Your monthly balance
<br />
<span>{{ test }}</span>
</div>
</div>

Update component when the store changes

I'm trying to update a component based on store updates, the objective of that is, when I click on a table item, I want to update the form buttons to edit form, and Edit the table item.
My source code:
I have an action which updates currentUser. currentUser is the user I want to update
src/actions/user.js
export const updateCurrentUserSuccess = (currentUser) => {
return {
type: UPDATE_CURRENT_USER,
currentUser
}
}
export const updateCurrentUser = (id) => {
return (dispatch) => {
return axios.get(`${apiUrl}/users/${id}`)
.then(response => {
console.log(response.data.data)
dispatch(updateCurrentUserSuccess(response.data.data))
})
.catch(error => {
throw (error);
});
};
};
my currentUserReducer:
src/reducers/currentUserReducer.js
import { UPDATE_CURRENT_USER } from '../constants/ActionTypes';
const initialState = {
currentUser: [],
}
export default function userReducer(state = initialState, action) {
switch (action.type) {
case UPDATE_CURRENT_USER:
return action.currentUser;
default:
return state;
}
}
now my components:
my NewUser form:
src/components/NewUser.js
import React, { Component } from 'react';
import { Store } from '../store'
class NewUser extends Component {
state = {
id: '',
name: '',
cpfcnpj: '',
isEdit: false
};
componentDidMount(){
this.handleUserChange()
}
handleInputChange = e => {
this.handleUserChange();
this.setState({
[e.target.name]: e.target.value
});
};
handleSubmit = e => {
e.preventDefault();
if (!this.state.isEdit) {
if (this.state.name.trim() && this.state.cpfcnpj.trim()) {
this.props.onAddUser(this.state);
this.handleReset();
}
} else {
if (this.state.name.trim() && this.state.cpfcnpj.trim() && this.state.id !== '') {
this.props.onEdit(this.state);
this.handleReset();
}
}
};
handleReset = () => {
Store.getState().currentUser = []
this.setState({
id: '',
name: '',
cpfcnpj: '',
isEdit: false
});
};
handleUserChange() {
console.log('store', Store.getState().currentUser._id);
if (Store.getState().currentUser._id !== undefined) {
this.setState({
id: Store.getState().currentUser._id,
name: Store.getState().currentUser.name,
cpfcnpj: Store.getState().currentUser.cpfcnpj,
isEdit: true
});
}
}
render() {
return (
<div>
<form className="form-inline" onSubmit={this.handleSubmit}>
<div className="form-group margin-right">
<input
type="text"
placeholder="Name"
className="form-control"
name="name"
onChange={this.handleInputChange}
value={this.state.name}
/>
</div>
<div className="form-group margin-right">
<input
type="text"
placeholder="CPF/CNPJ"
className="form-control"
name="cpfcnpj"
onChange={this.handleInputChange}
value={this.state.cpfcnpj}>
</input>
</div>
<div className="form-group">
<button type="submit" className={this.state.isEdit ? "btn btn-success margin-right hidden" : "btn btn-success margin-right"}>
<span className="glyphicon glyphicon-plus" aria-hidden="true"></span>
Adicionar
</button>
<button type="submit" className={this.state.isEdit ? "btn btn-primary margin-right" : "btn btn-primary margin-right hidden"}>
<span className="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>
Salvar
</button>
<button type="button" className="btn btn-default margin-right" onClick={this.handleReset}>
<span className="glyphicon glyphicon-erase" aria-hidden="true"></span>
Limpar
</button>
</div>
</form>
</div>
);
}
}
export default NewUser;
my component User item:
***src/components/User.js***
import React from 'react';
export default ({ user: { name, cpfcnpj, _id }, onDelete, onEditUser }) => {
return (
<tr>
<th scope="row">{name}</th>
<td>{cpfcnpj}</td>
<td>
<button className="btn btn-warning btn-xs margin-right" type="button" onClick={() => onEditUser(_id)}>
<span className="glyphicon glyphicon-edit" aria-hidden="true"> </span>
Editar
</button>
<button className="btn btn-danger btn-xs margin-right" type="button" onClick={() => onDelete(_id)}>
<span className="glyphicon glyphicon-trash" aria-hidden="true"> </span>
Excluir
</button>
</td>
</tr>
);
};
now my smart components:
src/containers/UserList.js
import React from 'react';
import { connect } from 'react-redux';
import User from '../components/User';
import { deleteUser, updateCurrentUser } from '../actions/user';
import NewUser from '../components/NewUser';
function UserList({ users, onDelete, onEditUser }) {
if (!users.length) {
return (
<div className="margin-top">
No Users
</div>
)
}
return (
<div className="margin-top">
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Nome</th>
<th scope="col">CPF/CNPJ</th>
</tr>
</thead>
<tbody>
{users.map(user => {
return (
<User user={user} onDelete={onDelete} onEditUser={onEditUser} key={user._id} />
);
})}
</tbody>
</table>
</div>
);
}
const mapStateToProps = state => {
return {
users: state.users
};
};
const mapDispatchToProps = dispatch => {
return {
onDelete: id => {
dispatch(deleteUser(id));
},
onEditUser: (id) => {
dispatch(updateCurrentUser(id))
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(UserList, NewUser);
src/containers/CreateUser.js
import { connect } from 'react-redux';
import { createUser, updateUser } from '../actions/user';
import NewUser from '../components/NewUser';
const mapDispatchToProps = dispatch => {
return {
onAddUser: user => {
dispatch(createUser(user));
},
onEdit: (id, name, cpfcnpj) => {
dispatch(updateUser(id, name, cpfcnpj))
}
};
};
export default connect(
null,
mapDispatchToProps
)(NewUser);
src/App.js
import React, { Component } from 'react';
import CreateUser from './containers/CreateUser';
import UserList from './containers/UserList';
import './css/main.css'
class App extends Component {
render() {
return (
<div className="container">
<h1 className="styles-app">Usuários</h1>
<div className="row styles-app">
<div className="col-md-12">
<CreateUser />
</div>
<div className="col-md-12">
<UserList />
</div>
</div>
</div>
);
}
}
export default App;
Here is something you might try. Connect your NewUser.js to the store.
import { connect } from 'react-redux;
export default connect(mapStateToProps)(NewUser);
Then map your currentUser state to props.
const mapStateToProps = state => {
return {
currentUser: state.currentUser
};
};
In your currentUserReducer
initialState = {
//Assuming these are the only values in response
id: '',
name: '',
cpfcnpj: '',
isEdit: false
};
export default function userReducer(state = initialState, action) {
switch (action.type) {
case UPDATE_CURRENT_USER:
return {
...state,
id: action.currentUser.id,
name: action.currentUser.name,
cpfcnpj: action.currentUser.cpfcnpj,
isEdit: true
};
default:
return state;
}
}
You should have access to the current user object now in props.
Then in your input value field
value={this.props.currentUser.name}
value={this.props.currentUser.cpfcnpj}
You may also need to do a check to see if these values have been updated. Also, not sure if the placeholder text might interfere.
Hope this gets you closer to the solution.
Edit
In the case of clearing props, you might just add another action to do so.
In your actions for currentUser:
export const clearUserData = () => {
return {
type: CLEAR_USER_DATA,
}
}
And in your reducer:
export default function userReducer(state = initialState, action) {
switch (action.type) {
case UPDATE_CURRENT_USER:
return {
...state,
id: action.currentUser.id,
name: action.currentUser.name,
cpfcnpj: action.currentUser.cpfcnpj,
isEdit: true
};
case CLEAR_USER_DATA:
return {
...state,
id: '',
name: '',
cpfcnpj: '',
isEdit: false
};
default:
return state;
}
}
Add the clearUserData action to execute after you submit your edits and it should reset your reducer. You might even be able to just do
return {
...state,
initialState
};

Categories