Accessing nested object - javascript

I'm having some trouble accessing the properties in the nested object. I've tried:
<p>{this.state.post.user.firstName}</p>
<p>{this.state.post.comments[0].user.firstName}</p>
Both lines don't not work, only <p>{this.state.post.date}</p> works.
Component:
state = {
post: {}
}
async componentDidMount() {
const { post_id } = this.props.match.params;
const response = await axios.get(`/posts/${post_id}`);
this.setState({
post: response.data
})
}
render() { return( ...... )}
Here's an example of my json:
{
"date": "2018",
"user": { "firstName": "Some Name" },
"comments": [
{
"body": "here's my comment."
"user": {
"firstName": "Some Name",
"lastName": "Some Lastname"
}
},
{......}
]
}
The error I'm getting:
TypeError: Cannot read property 'firstName' of undefined
TypeError: Cannot read property '0' of undefined

You are most likely getting these errors because you are not taking into consideration that post is initially an empty object, which will cause this.state.post.user.firstName and this.state.post.comments[0] to throw an error.
You could do this instead:
class MyComponent extends React.Component {
state = {
post: null
}
async componentDidMount() {
const { post_id } = this.props.match.params;
const response = await axios.get(`/posts/${post_id}`);
this.setState({
post: response.data
});
}
render() {
const { post } = this.state;
return post ? (
<div>
<p>{post.user.firstName}</p>
<p>{post.comments[0].user.firstName}</p>
<p>{post.date}</p>
</div>
) : null;
}
}

Related

Using strapi V4 graphql and nextjs - filters not work

I´m using strapi V4 with the graphql extension. When i´m use filters with variables in the graphql Playground there are no problems.
query getOrdersFilterList($searchstring: String!) {
orders(filters: { customer: { contains: $searchstring } }) {
data {
attributes {
number
customer
name
article
}
}
}
}
Query Variables:
{
"searchstring": "zi"
}
When i use filters with Postman no problems.
query getOrdersFilterList($searchstring: String) {
orders(filters: {customer: { containsi: $searchstring}}) {
data {
attributes {
number
customer
name
article
}
}
}
}
Graphql Variables :
{
"searchstring": "zi"
}
The result is like expected:
{
"data": {
"orders": {
"data": [
{
"attributes": {
"number": "30072",
"customer": "Stauder Zimmerei",
"name": "Hagmann Habsburgerstr.",
"article": "Stahlteile "
}
},
{
"attributes": {
"number": "22-02-015 A",
"customer": "Ziebarth Wolfgang",
"name": "Austr. 1 a",
"article": "Aussengeländer "
}
},
{
"attributes": {
"number": "30013",
"customer": "Ziser",
"name": "Bürklinstraße 7, Lahr",
"article": "Geländer mit Mlichglas "
}
}
]
}
}
}
Now my nextjs app code:
export const getOrdersFilterList = async (page, pageSize, searchstring) => {
const data = await client.query({
query: gql`
query getOrdersFilterList($searchstring: String) {
orders(filters: {customer: { contains: $searchstring}}){
data {
attributes {
number
customer
name
article
}
}
}
}`,
variables: {searchstring}
})
Variables same as above ( searchstring come from the call of the function )
{
"searchstring": "zi"
}
this is what i get on the console (Firefox):
" Object { data: {…}, loading: false, networkStatus: 7 } "
I spend days to search. I can´t find a clue
Anyone can help ?
solved !
The Problem was the Variable
{
"searchstring": "zi"
}
In every Tutorial or example i find it like above.
But the only thing your Variable must contain is
zi
let´s explain in the code :
export const getOrdersFilterList = async () => {
// this is the variable
const searchstring = "zi"
// thats all
const data = await client.query({
query: gql`
query getOrdersFilterList($searchstring: String) {
orders(filters: {customer: { containsi: $searchstring}}){
data {
attributes {
number
customer
name
article
}
}
}
}`,
variables: {searchstring}
})

Error: A required parameter (productId) was not provided as a string in getStaticPaths for /products/[productId]

I would like to show 3 products from a JSON. I'm trying to do a NextJS web application. I'm just learning, and when I replicate the tutorial is everything correct, but I'm doing my own changes, and trying to create something different, but it doesn't work.
Thanks to all!
[
{
"id": "price_1JDUeIIpi9NgmDuQlNYIwAlP",
"title": "HarryPotter1",
"category": "Cuento",
"image": "/images/harrypotter1.jpeg",
"price": 20
},
{
"id": "price_1JDUe4Ipi9NgmDuQh9nA4B9E",
"title": "Harry Potter2",
"category": "Novela",
"image": "/images/harrypotter2.jpeg",
"price": 10
},
{
"id": "price_1JDUdqIpi9NgmDuQGOQO9HGj",
"title": "Harry Potter3",
"category": "Ensayo",
"image": "/images/harrypotter3.jpeg",
"price": 25
}
]
]
In different routes with Link. This is my [productId].js file final part:
export async function getStaticProps({ params = {} }) {
const product = products.find(({ id }) => `${id}` === `${params.productId}`);
return {
props: {
product
},
};
}
export async function getStaticPaths() {
const paths = products.map((product) => {
const { id } = product;
return {
params: {
productId: id,
},
};
});
return {
paths,
fallback: false
};
}
I'm getting from Chrome: Error: A required parameter (productId) was not provided as a string in getStaticPaths for /products/[productId]
I can only assume based on the error description, that:
const { id } = product;
return {
params: {
productId: id,
},
};
In this part of the getStaticPaths function, you are supposed to provide the id for productId as a string (might be a number on its own).
So you would want to try changing it to this:
const { id } = product;
return {
params: {
productId: id.toString(),
},
};
Let me know if this is what you were looking for.

Failing to render my search to the browser

I am trying to filter my todos based on their status i.e; complete and incomplete. I have written down all the code that is required to get it but I get this kind of error:
index.js:29 Uncaught TypeError: Cannot read property 'toLowerCase' of undefined
at index.js:29
at Array.filter (<anonymous>)
at renderTodos (index.js:28)
at index.js:47
Here is my actual code to help me render the filtered todos to the browser:
const todos = [
{
todo: "Pray",
status: "false",
},
{
todo: "Shower",
status: "true",
},
{
todo: "Eat",
status: "true",
},
{
todo: "Run",
status: "false",
},
{
todo: "Work",
status: "false",
},
];
const filters = {
searchText: "",
};
const renderTodos = function (todos, filters) {
const filteredTodos = todos.filter(function (todo) {
return todo.text.toLowerCase().includes(filters.searchText.toLowerCase());
});
const incompleteTodos = filteredTodos.filter(function (todo) {
return !todo.status;
});
document.querySelector("#todos").innerHTML = "";
const summary = document.createElement("h1");
summary.textContent = `You have ${incompleteTodos.length} todos left`;
document.querySelector("#todos").appendChild(summary);
todos.forEach(function (todo) {
const p = document.createElement("p");
p.textContent = todo.text;
document.querySelector("#todos").appendChild(p);
});
};
renderTodos(todos, filters);
document.querySelector("#search").addEventListener("input", function (e) {
filters.searchText = e.target.value;
renderTodos(todos, filters);
});
Your todo object does not have a text property but just status and todo; you probably wanted to filter by todo:
const filteredTodos = todos.filter(function (todo) {
return todo.todo.toLowerCase().includes(filters.searchText.toLowerCase());
});
it looks like the error is in the line :-
return todo.text.toLowerCase().includes(filters.searchText.toLowerCase());
Here you're trying to access the text property of the todo object, which is not available in the objects of the todos array. It only has todo and status property.
so the code will look like this...
return todo.todo.toLowerCase().includes(filters.searchText.toLowerCase());

Why does vue.js alter my JSON data?

I want to return data from my API and display it in a vue.js project.
The data is:
{
"pages":[
{
"id":3,
"slug":"over-mij",
"updated_at":"2017-12-25T11:16:21+01:00",
"created_at":"2017-12-25T10:56:21+01:00",
"title":"Over mij",
"content":""
},
{
"id":6,
"slug":"mijn-cv",
"updated_at":"2017-12-25T11:07:29+01:00",
"created_at":"2017-12-25T11:07:29+01:00",
"title":"Mijn cv",
"content":null
}
],
"current_user":null
}
Then I'm using vue-resource to load the data from my API page in a seperate module of vuex:
const actions = {
initPages({commit}) {
Vue.resource('pages').get({}).then(function(response) {
if (response) {
response.json().then(data => {
state.pages = data;
});
}
});
}
}
The problem however is when I check what's inside the state.pages, this contains:
{
"pages": {
"pages": [
{
"id": 3,
"slug": "over-mij",
"updated_at": "2017-12-25T11:16:21+01:00",
"created_at": "2017-12-25T10:56:21+01:00",
"title": "Over mij",
"content": ""
},
{
"id": 6,
"slug": "mijn-cv",
"updated_at": "2017-12-25T11:07:29+01:00",
"created_at": "2017-12-25T11:07:29+01:00",
"title": "Mijn cv",
"content": null
}
],
"current_user": null
}
}
For some weird reason my JSON response is altered, I've already tried setting state.pages to data.pages and this just eliminates the first pages object but not the second one.
When I set my state.pages to data.pages[0] it does work, does anyone know why this is happening?
Even when I use mutations, I still have the same issue:
module of store.js:
import Vue from 'vue';
const state = {
pages: []
}
const mutations = {
'setPages' (state, pages) {
state.pages = pages;
}
}
const getters = {
pages(state) {
return state.pages;
},
page(state) {
return keyword => state.pages.find(function(page) {
return page.slug === keyword;
});
}
}
const actions = {
initPages({commit}) {
Vue.resource('pages').get({}).then(function(response) {
if (response) {
response.json().then(data => {
commit('setPages', data.pages);
});
}
});
}
}
export default {
state,
getters,
mutations,
actions
}

Reactjs: Why my props aren't being updated?

I need to update my props in order to render new data.
I have a view with a list of dealers for a casino game. That list is OK, the problem comes up when you try to add a new dealer, the dealer doesn't display in the view, yo have to reload the page in order to see the new change.
Let me show you my code starting in the actions
action
class CreateDealersActions {
constructor () {
this.generateActions('createDealerSuccess');
}
createDealer (data) {
const that = this;
that.dispatch();
axios.post(`${API_ENDPOINT}/create-dealer/create-dealer`, data)
.then(function success (response) {
that.actions.createDealerSuccess({response});
})
}
}
store
class GetDealersStore {
constructor () {
this.state = {
dealerData : null,
};
}
#bind(GetDealersActions.dealerDataSuccess)
dealerDataSuccess (data) {
this.setState({
dealerData : data,
});
}
#bind(CreateDealersActions.createDealerSuccess)
createDealerSuccess (data) {
this.setState({
dealerData : data,
});
}
}
the dealerDataSuccess() is the function I call when the view loads in order to render the list of dealers, and createDealerSuccess() is the one called when you attempt to add a new dealer.
here you will see what every function returns
if you put in dealerDataSuccess() console.log(JSON.stringify(data));
{"dealersData": [{
"DealerId":"1",
"DealerName":"Carmen",
"NickName":"Carmen",
"Picture":"url",
"Active":"1",
"LegalId":"13",
"TypeId":"1"}
]}
but if you put in createDealerSucess() console.log(JSON.stringify(data)); it returns something like this:
{
"response": {
"data": {
"success": "New dealer successfully inserted."
},
"status": 200,
"statusText": "OK",
"headers": {
"content-type": "application/json; charset=utf-8"
},
"config": {
"method": "post",
"headers": {
"Content-Type": "application/json;charset=utf-8"
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"url": "http://localhost:1102/services/create-dealer/create-dealer",
"data": {
"DealerName": "my Name",
"CardId": "1221",
"NickName": "newName",
"Picture": "url",
"Active": "1",
"LegalId": "321321",
"TypeId": "1"
}
}
}
}
the component code
component
#connectToStores
export default class Dealers extends Component {
static contextTypes = {
router : React.PropTypes.func,
}
constructor (props) {
super(props);
this.state = {}
}
componentWillMount () {
GetDealersActions.getDealers();
}
static getStores () {
return [ GetDealersStore ];
}
static getPropsFromStores () {
return {
...GetDealersStore.getState(),
}
}
render () {
return (<html for component>);
}
_addDealer = () => {
CreateDealersActions.createDealer({
DealerName : this.refs.DealerName.getValue(),
CardId : this.refs.CardId.getValue(),
});
}
}
now in the component part there is componentWillMount(), if you put console.log(JSON.stringify(this.props)); it returns
{"params":{},"query":{},"dealerData":null}
and if you put in _addDealer console.log(JSON.stringify(this.props)); where it suppose to add the new dealer you get the whole props but without the last dealer you add, so you have to refresh the page in order to see the new dealer in the view/screen.
What do you think is going on here ?
PS: if you similar question about this from me, take into account that in the other question I was 2 using different stores, here I am using just one
EDIT
the Dealers component is within a tab named management, which is this one:
const menuItems = [
{ route : 'dealers', text : 'Dealers' },
{ route : 'game-info', text : 'Game Info' },
{ route : 'player-info', text : 'Players Info' },
{ route : 'money', text : 'Money' }
];
export default class Management extends React.Component {
static propTypes = {
getActivePage : React.PropTypes.func,
menuItems : React.PropTypes.arrayOf(React.PropTypes.object),
}
static contextTypes = {
router : React.PropTypes.func,
}
render () {
return (
<div>
<TabsMainMenu menuItems={menuItems} getActivePage={this._getActivePage} />
<RouteHandler />
</div>
);
}
_getActivePage = () => {
for (const i in menuItems) {
if (this.context.router.isActive(menuItems[i].route)) return parseInt(i, 10);
}
}
}

Categories

Resources