setState an array and object - reactjs

How do you setState an object and an array at the same time after passing id and data to a function? Because comment is not part of an array, I'm getting confused.
this.state = {
tasks: [
{ firstName: "boris", lastName: "Johnson", id: uuid() },
{ firstName: "Mary", lastName: "Whithaker", id: uuid() }
],
comment: "This is a comment message"
};
updateTask(id, task, comment, additional) {
const updatedProject = this.state.tasks.map(t => {
if (t.id === id) {
return {
...t,
firstName: task,
lastName: comment
};
}
return t;
});
this.setState({ tasks: updatedProject, comment: additional });
}

Your State is an object.
In that object there are two fields, tasks and comment.
Tasks is an array of objects, those objects have firstname, lastname and id fields.
Comment is a string.
When that code is doing setState at the end, it is creating a new object (see the {}), and then giving it the updatedProject array for tasks, and then the additional string for comment.
That whole object is then set. The array and string are values of fields in that object.

Related

How to use if condition inside an object in react

I'm trying to pass some data as payload to the api and I'm struggling to put condition inside of the object. I have an object called payload and I want to pass it in the api by checking the value of the state called profession.
const payload ={
name: registerData.fullname,
password: registerData.password,
confirm_password: registerData.confirmPassword,
email: registerData.email,
additional_info: {
profession == "Student" ? (
universityname: values.universityname,
course: values.course,
start_year: values.start_year,
end_year: values.end_year, ) :
(professorUniversity: values.professorUniversity,
department: values.department,
organizationName: values.organizationName,
organizationLocation: values.organizationLocation,
investorCompany: values.investorCompany,
investorCompanyWebsite: values.investorCompanyWebsite,
companyName: values.companyName,
govtSector: values.govtSector,
govtDesignation: values.govtDesignation,
)
},
};
// I'm passing the payload in the api.
api.post("some-url/register", payload);
as you can see in the top I want to pass the entire key and value if the condition is true. If the profession is not student I don't even pass the universityname key.
You should use a combination of ternary and spread operator
const payload ={
name: registerData.fullname,
password: registerData.password,
confirm_password: registerData.confirmPassword,
email: registerData.email,
additional_info: {
...(profession == "Student" ? {
universityname: values.universityname,
course: values.course,
start_year: values.start_year,
end_year: values.end_year, } :
{professorUniversity: values.professorUniversity,
department: values.department,
organizationName: values.organizationName,
organizationLocation: values.organizationLocation,
investorCompany: values.investorCompany,
investorCompanyWebsite: values.investorCompanyWebsite,
companyName: values.companyName,
govtSector: values.govtSector,
govtDesignation: values.govtDesignation,
})
},
};
I have explained something similar here
An example:
let car = "BMW";
const result = {
...(car === "BMW" ? {
make: "Germany"
} : {
make: "other"
})
};
console.log(result);

Insert list data over the iteration(map)

Here I am trying to modify my data over the iteration and send some result to API call.
The API Call receives a request with a structured data format which is
{ list: [{ id: "1", name: "Hello" }, ... ] }
Somehow I managed to call the API with single data ( const params in my current code, it only accepts single data).
But now it has to be done with multiple data something like this:
{ list: [{ id: "1", name: "Hello" }, { id: "22", name: "Ed" }, { id: "36", name: "Jason" } ... ] }
Here is my current code
const [table, setTalbe] = useState(..); // assume, we have some table data here
const processNow = () => {
let id = 0;
let name = '';
// if table length is greater than 1, we go for the loop.
if (table.length >= 1) {
table.map(data => {
id = data.userId;
name = data.userName;
});
//insert table data to params, here I want to add whole table data into "list"
//the final result of this list should be something like this
//ex ) list: [{ id: '123', name: 'Josh' }, { id: '125', name: 'Sue' }, { id: '2222', name: 'Paker' } ...],
// but how??
const params: any = {
list: [
{
id: id,
name: name
},
],
};
//send PUT reqeust with params
axios
.put(
'/api/v1/tosent',
params,
)
.then(res => {
console.log('The response', res);
})
.catch(err => {
console.log('The error: ', err);
});
}
};
but I'm stuck with it, please help me to finish this code to work properly.
need your kind advice.
Array.prototype.map returns a new array with the function you pass applied to every element. You should study the MDN documentation on map to understand its use.
Your current code does nothing with the map return value:
table.map(data => {
id = data.userId;
name = data.userName;
});
You probably assumed .map would mutate the data, as in change it in place. Instead, the whole operation returns a new array.
It looks like you want to do:
const list = table.map(data => {
return {
id: data.userId,
name: data.userName
}
});
This is applying a function to every element in the array that will map each element to a new object, matching your question, with an id and name key. Then it looks like you want to pass the returned value of map (which we named list above) to your call:
const params: any = {
list: list
};

Graphql mutation query : how to access the data elements

const MUTATION_QUERY = gql`
mutation MUTATION_QUERY(
$name: bigint!
) {
insert_name(
objects: {
name: $name
}
) {
returning {
id
name
}
}
}
`;
const [onClick, { error, data }] = useMutation<{}, {}>(MUTATION_QUERY, {
variables: {
name: 1234,
},
});
My mutation query is inserting name in my table and autogenerating the id. On console logging the data variable I can view the fields id and name in the data object. But I am not able to access them them individually. How can I console.log "id". Thank you.
the console.log(data) looks like : {insert_name: {...}}
which expands to :
insert_name:
returning: Array(1)
0: {id: 1, name: 1234}
length: 1
_proto_: Array(0)
_typename: "insert_name_mutation_response
You can access the fields of an object with .
For example, if your object looks like this -
data = {
id: 1,
name: 'Jane',
}
You can get just the id with data.id
This works no matter how many layers deep your object may go, so take this example -
data = {
person: {
id: 1,
name: 'Jane',
}
}
You could get the id of person with data.person.id.
console.log(data.insert_name.returning[0].id) will give you the id returned.
For it to work in typescript we need to change the query to add the return type of data
const [onClick, { error, data }] = useMutation<{ReturnInsertNameProps}, {}>(MUTATION_QUERY, {
variables: {
name: 1234,
},
});
interface ReturnInsertNameProps {
insert_name: ReturnQueryProps;
}
interface ReturnProps {
returning: MessageProps[];
}
interface NameProps {
id: number;
name: number;
}
We can also use onCompleted method provided in useMutation if we want to process the result of the query.

How can I access all elements with a particular attribute in graphQL?

I have some json data in file called countryData.json structured as so:
{
"info":"success",
"stats":
[{
"id":"1",
"name":"USA",
"type":"WEST"
},
//...
I'm using graphQL to access this data. I have created an object type in the schema for countries using the following:
const CountryType = new GraphQLObjectType({
name: "Country",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
type: { type: GraphQLString },
})
});
I want to write a query that will allow me to access all of the elements of this array that have a certain "name" value(There can be multiple with the same name). I've written the following query, but it only returns the first match in the array:
const RootQuery = new GraphQLObjectType({
name:"RootQueryType",
fields:{
country: {
type: CountryType,
args: { type: { name: GraphQLString } },
resolve(parent, args){
return _.find(countryData.stats, {name: args.name});
}
}
}
});
The "_" comes from const _ = require('lodash');
Also, how can I just get every single item in the array?
I have not recreated the code, therefore I can not check if it would be executed correctly. This is code, that should work in my opinion (without trying). If you want to return array of elements you need to implement https://lodash.com/docs/#filter. Filter will return all objects from stats, which match the argument name. This will return correctly inside resolver function, however, your schema needs adjustments to be able to return array of countries.
You need probably rewrite the arguments as follows as this is probably not correct. You can check out how queries or mutation arguments can be defined https://github.com/atherosai/express-graphql-demo/blob/feature/2-json-as-an-argument-for-graphql-mutations-and-queries/server/graphql/users/userMutations.js. I would rewrite it as follows to have argument "name"
args: { name: { type: GraphQLString } }
You need to add GraphQLList modifier, which defines, that you want to return array of CountryTypes from this query. The correct code should look something like this
const RootQuery = new GraphQLObjectType({
name:"RootQueryType",
fields:{
country: {
type: CountryType,
args: { name: { type: GraphQLString } },
resolve(parent, args){
return _.find(countryData.stats, {name: args.name});
}
},
countries: {
type: new GraphQLList(CountryType),
args: { name: { type: GraphQLString } },
resolve(parent, args){
return _.filter(countryData.stats, {name: args.name});
}
}
}
});
Now if you call query countries, you should be able to retrieve what you are expecting. I hope that it helps. If you need some further explanation, I made the article on implementing lists/arrays in GraphQL schema as I saw that many people struggle with similar issues. You can check it out here https://graphqlmastery.com/blog/graphql-list-how-to-use-arrays-in-graphql-schema
Edit: As for the question "how to retrieve every object". You can modify the code in resolver function in a way, that if the name argument is not specified you would not filter countries at all. This way you can have both cases in single query "countries".

How to save an empty array as property of a nested object in mongoose?

I have the following code:
var lesson = new Lesson({
classroomId: req.params.classroomId,
name: req.body.name,
startDate: startDate1,
endDate: endDate1,
teacher: {
_id: classroom.teacher._id,
attendance: [],
},
students: [],
});
lesson.save();
When I check in the backend, the teacher key just has the _id property and the attendance property wasnt saved. I suspect this is because it is an empty array. How can I save an empty array like this?
It may be because Lesson Schema is not defined properly. Did you try setting...
mongoose.Schema({
.....
teacher: {
...
attendance: { type: Array, default: [] }
}
...
});

Resources