Hi Im having troubles setting the state when I press a button 'Send' on one email input.
I'm trying it avoiding mutation as React docs recommends.
My state properties are this:
state = {
emailForm: {
email: {
elementType: 'email-invitation-input',
elementConfig: {
type: 'email',
placeholder: 'Enter an email..',
},
value: '',
valid: true,
required: true
}
},
requestStatus : false,
validationMessage : null,
formIsValid: false,
}
So I tried three ways to set empty value to my email input trough the state but no one worked :(
First try:
I used ES6 spread operator to change it value but it doesn't change the input value:
this.setState({
email: {
...this.state.emailForm.email,
value: '',
},
});
this.setState({
email: Object.assign({}, this.state.emailForm.email, {
value: '',
}),
});
Another try using immutability-helper package
import update from 'immutability-helper';
let newData = { email: {
...this.state.emailForm.email,
value: '',
}, };
this.setState({
email: update(this.state.newData, {
value: {$set: newData},
})
});
Second try:
I used Ramda.js but it neither works.
setObjectByPath(fieldPath, value) {
this.setState({
emailForm: R.set(R.lensPath(fieldPath), value, this.state.emailForm)
})
}
setObjectByPath(this.state.emailForm.email,'');
Third try:
I used react-addons-update:
import update from 'react-addons-update';
this.setState({
email: update(this.state.newData, {
value: {$set: newData},
})
});
All tries does nothing or it creates a new email input with empty value below.
Thanks beforehand
this.setState(prevState => ({
emailForm: {
email: {
...prevState.emailForm.email,
value: ''
}
}
}));
Related
So I'm trying to change a specific key in a model on my database given a specific argument in a function. I can of course do it as repeating if statements, but it's of course not very lucrative or sustainable. Given that in my actual application the keyX goes all the way up to 9, I'm not very enticed to solve this problem like this. The example below is of course a simpler enactment of my problem.
//model.js
const { DataTypes } = require('sequelize');
const db = require('../database/connection');
const model = db.define('exampleModel', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
key1: { type: DataTypes.STRING },
key2: { type: DataTypes.STRING },
key3: { type: DataTypes.STRING },
//keyN...
someotherKey: { type: DataTypes.ARRAY(DataTypes.JSON) }
});
module.exports = model
//insertions.js
const { model } = require('../models/model')
async function insert(argument) {
if(argument === 1) { model.update({ key1: 'something' }) }
if(argument === 2) { model.update({ key2: 'something else' }) }
if(argument === 3) { model.update({ key3: 'something else entirely' }) }
}
insert(2); //desired outcome here is the function only updating the text of key2
Essentially I want to change only a specific key depending on what my given argument for the function is. A fix i tried initially was:
const desiredKey = `key{argument}`
model.update({ [desiredKey]: "completely new text" })
But proved to not do much for me.
Seems like you forgot to prepend argument by $:
const fieldName = `key${argument}`;
await model.update({ [fieldName]: "completely new text" })
I am trying to call a getter method and it's not getting called for some reason. If I console.log the store I can see that it's undefined:
This is where I'm calling the getter method:
computed: {
client() {
console.log(this.$store); //see above screenshot
console.log(this.$route.params.id); //shows a valid value.
//nothing seems to happen after this point, console.log in the below getter doesn't happen.
return this.$store.getters['clients/clientById', this.$route.params.id];
}
},
here's my getter in clients.js module:
getters: {
clients(state) {
return state.clients;
},
hasClients(state) {
return state.clients.length > 0;
},
clientById(state, id) {
console.log('test'); //this doesn't happen
return state.clients.find(client => client.id === id);
}
}
The first 2 getter methods are working fine, using the same syntax as what I'm doing when I'm calling the clientById getter.
What I'm trying to accomplish is to have an array of client objects, and then when a user clicks on a client in the client list, I grab the ID out of the route params and the appropriate client data is displayed on the page. I'd appreciate any guidance on whether I'm approaching this in the right way as well as I'm new to Vue.
state() {
return {
clients: [
{
id: null,
client_name: '',
address: '',
city: '',
state: '',
zip:'',
created_at: '',
updated_at: '',
deleted_at: null
},
]
};
},
UPDATE:
I'll provide my entire clients.js module in case something is off with that. Everything else seems to be working fine, so not sure if this is related or not. This is an updated version of the getter where I changed it to an arrow function based on your feedback. When I do this, I get another error: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them at Function.
I've also tried hard-coding the ID within the getter method and taking it out of the passed-in ID parameter, and that seems to work, but is returning undefined, so it's still not getting a value from state.
import axios from "axios";
export default {
namespaced: true,
state() {
return {
isLoading: false,
clients: [
{
id: null,
client_name: '',
address: '',
city: '',
state: '',
zip:'',
created_at: '',
updated_at: '',
deleted_at: null
},
]
};
},
mutations: {
setLoadingStatus(state, status) {
state.isLoading = status;
},
setClients(state, clients) {
state.clients = clients;
}
},
actions: {
async fetchClients(context) {
context.commit('setLoadingStatus', true);
try {
const resp = await axios.get('http://localhost/api/clients');
context.commit('setLoadingStatus', false);
context.commit('setClients', resp.data);
} catch(e) {
console.log(e);
}
}
},
getters: {
clients(state) {
return state.clients;
},
hasClients(state) {
return state.clients.length > 0;
},
clientById: (state) => (id) => {
return state.clients.find(client => client.id === id);
}
}
};
I need to transfer state of a component to its parent component, but I don't need to transfer all fields.
What I currently do:
submitHandler = (e) => {
e.preventDefault();
const newState = Object.keys(this.state).map(item => {
if(item !== 'errors')
{
return { item: this.state[item] }
}
});
console.log(newState);
this.props.onChange(newState);
}
Obviously it is not what I need.
state = {
errors: {
fio: '',
email: '',
phone: ''
},
owner: owner.Company,
fio: null,
company: null,
phone: null,
fax: null,
email: null,
adress: null
}
I need to transfer all field except errors. How can I do that?
You can use the rest operator for making it work :)
const { errors, ...newState } = this.state;
this.props.onChange(newState);
I put an example here :) https://repl.it/#EQuimper/PleasantTrimDeclarations
Object destructuring with the rest operator provides a convenient way to copy objects, while omitting specific fields. In the example below, newState will be a copy of this.state, minus the errors property:
submitHandler = e => {
e.preventDefault();
const { errors, ...newState } = this.state;
this.props.onChange(newState);
};
I have a component that contains a default object, and on create GETs a populated object. When trying to bind this.profile to the new object it seems to get the correct data in the method but the change is not pushed back to other uses of this.profile. Is there a way to force this change to be picked up by the rest of the script?
export default {
data() {
return {
profile: {
firstName: 'Seller First Name',
surname: 'Seller Surname',
username: '',
biography: 'Seller biography.',
phoneNumber: 'Seller Phone Number',
emailAddress: 'Seller Email',
profilePhotoUrl: '',
testimonials: []
}
};
},
components: {
ProfileSummary,
Biography,
TestimonialList,
PaymentsenseCompany
},
created() {
console.log('created');
this.getProfile(this.$route.params.sellerUsername);
},
methods: {
getProfile(sellerUsername) {
axios.get('http://fieldsellerprofileapi.azurewebsites.net/api/fieldseller/' + sellerUsername)
.then(function(response) {
this.profile = Object.assign({}, response.data);
Vue.nextTick(() => {
console.log('after', this);
});
}.bind(this))
.catch(e => {
console.log(e);
// location.replace('/404');
});
}
},
Im not sure, but try this:
getProfile(sellerUsername) {
axios
.get('http://fieldsellerprofileapi.azurewebsites.net/api/fieldseller/' + sellerUsername)
.then(r => this.profile = r.data)
.catch(e => console.log(e))
}
So it turns out the issue wasn't that the values weren't being updated. They were being saved fine, I was just trying to access them in a child component which was not being updated with the parent for some reason. The changes were not propagating down to the children... This may be of use researching if you have the same issue.
Thanks
I have an immutable object as my state in a redux reducer, and am trying to add/updates objects to a list.
Here's my reducer:
import { fromJS } from 'immutable'
const initialState = fromJS({
editable: true
})
export default (state = initialState, action) => {
switch(action.type) {
case 'CONTENT_MODE': {
return state.set('editable', action.editable ? false : true)
}
case 'UPDATE_CONTENT': {
return state.set(action.page, action.content)
// action.page = String
// action.content = {}
}
default: {
return state
}
}
}
I want to add objects to the page key, however if it currently exists update the values. I've tried updateIn and add() the callback, but I'm fairly new to immutable.js and am not sure how to approach it correctly.
The set() method rewrites the 'page' value entirely, whilst I need to push the value and only set if it exists, ending up with:
Example
const initialState = fromJS({
editable: true,
home: {
title: {
name: 'this is the name',
value: 'this is the value'
},
body: {
name: 'this is the name',
value: 'this is the value'
}
},
page1: {
title: {
name: 'this is the name',
value: 'this is the value'
},
body: {
name: 'this is the name',
value: 'this is the value'
}
}
})
If you know the full path of where you want to add something from your action, you could use SetIn with a keypath. Example, say you want to add a footer to page1:
const footer = {name: 'Footer', value: "I'm a footer!" }
return state.setIn(["page1", "footer"], fromJS(footer)
If you need to update things (ie say footer has name and value but then you're updating it to also have a style property) you could use mergeIn which is more like Object.assign:
const myNewData = {footer: {style: "myStyle"}}
console.log(state.mergeIn(["page1"], fromJS(myNewData);
--> { page1: { name: 'Footer'
, value: "I'm a footer!"
, style: 'myStyle'
}
}
If you merged in another object, it would add to the props of page1. If that object had a property with the same name, the value would be overwritten.