"Cannot read property 'map' of undefined" react and node.js - node.js

https://github.com/dongha1992/MERN-boilerplate
enter image description here
hello. currently I tried to practice shopping mall clone as react and node.js
I faced that problem I attached. it doesn't seem that error for cos I copied same as tutorial but it is something wrong with node.js(localhost:5000)
I tried to everything to fix it but don't know how to approach. please help me!
enter image description here

Probably an asynchronous request that populates your props.images hasn't returned a response.
Prefix props.images && to props.images.map function
That way only when the prop is present does the the map occur. Like this
{props.images && props.image.map(image=>.........

Ok, this is often an issue of a variable taking on different value during code execution. To safeguard again this, it's recommended to make sure that the props or a specific variable is defined before it's used.
// alternative-1
function ImageSlider(props){
return props.images && (
<div>
<Carousel autoplay>
{props.images.map((image, index) =>
// ...
)}
// ...
</div>
);
};
OR
// alternative-2
function ImageSlider(props){
return props.images ? (
<div>
<Carousel autoplay>
{props.images.map((image, index) =>
// ...
)}
// ...
</div>
) : null;
};
Critically, here's what is happening in the return() statement.
Alternative-1 (Implicit):
The second part, <div> is only rendered if the first part is true.
In core JavaScript, undefined is equivalent to false so props.images is true only when images is !undefined (not undefined; in other words, images is defined).
Alternative-2 (Explicit):
This one is more direct, as long as props.image is undefined, we return null.(Remember, a valid react component must return something. If nothing, then return null)
Only when props.images is defined, then we return the <div>.
These added checks ensure that your code never breaks, in this case your map() will always be called on a defined variable (props.images).
Here's a good read on Conditional rendering from the react team.

It looks like you're trying to call the map function on data that hasn't been received from your axios request. You should add some logic so that any components that rely on your request data render only if it exits, easily done with a ternary operator.
It looks like many components (including imageSlider) depend on data you try to access when you call your renderCards function on line 54 of your App.

Related

Rendering one of multiple pages with lit-element

The lit-element documentation describes conditional rendering via (condition ? a : b). I was wondering how to use that to render one of multiple pages, f.e. in combination with mwc-tab-bar from Googles material web components.
My current solution is something like this:
render() {
... other stuff ...
${this.selectedPage === 0 ? html`
<div>
...
</div>
` : html``}
${this.selectedPage === 1 ? html`
<div>
...
</div>
` : html``}
... further pages ...
}
I don't like the :html`` part but is that how it's meant to be?
Use more simple code like this.
constructor(){
super();
// don't forget add `prop` and `selectedPage` to `static get properties()`
this.prop = 1;
}
render() {
return this.getPage(this.selectedPage);
}
getPage(num){
switch(num){
default:
case 1:
return html`<div>P${this.prop}<div>`;
case 2:
return html`<div>P2<div>`;
}
}
There are multiple ways of achieving this, your solution is one, but as you mention, it's not the prettiest
One way you could modularize this somewhat is using an object/array and render functions, basically the idea is this:
First, define render functions for each page (this can be on the same file or on different files):
const page0Renderer = (context) => {
return html`<section>${context.someData}</section>`;
};
Then, you could define an object that has a match between the page identifiers and their respective functions, you are using numbers so the sample below uses numbers:
const pageRenderers = {
'0': page0Renderer,
'1': page1Renderer,
'2': page2Renderer,
// etc
};
And in your main render function you could use all these like this:
render() {
return html`
${pageRenderers[`${this.selectedPage}`](this)}
`;
}
This would basically call the render function that matches the selected page and send it a reference to the main web component so that you can access its properties.
Then again, this approach also has its flaws and I wouldn't really recommend it much if you need your child templates to be complex.
In that case, instead of rendering functions you probably would be better off creating other components for each view and that way you could also do some lazy loading and so on.
For that kind of approach, you might want to check out routers like vaadin router which help you both with routing and changing which component gets displayed accordingly

How to setState of redux wrapped component?

I'm trying to test a component that is wrapped in Redux:
beforeEach(async () => {
component = await mount(
<Provider store={buildStore()}>
<CheckoutOverlay cartItems={basicCart} />
</Provider>
)
await component.update();
})
Things I've tried:
component.find(CheckoutOverlay).instance().state.coupon={} (Cannot read 'state' of null)
component.find(CheckoutOverlay).state.coupon={mode:0, value:.25}; (state does not update)
component.find(CheckoutOverlay).setState({coupon: {mode: 0, value: .25}}); (setState() can
only be called on class components)
component.find(CheckoutOverlay).instance().setState({coupon: {mode: 0, value: .25}}); (cannot read property 'setState' of null)
I've also tried some suggestions that use SHALLOW() and .dive(). But I always get the error 'dive()' is not a function. I am using Enzyme 3.11.0
How can I update the state of a component wrapped in the Redux Provider?
Additional Info:
Inside my component, CheckoutOverlay, I have another component that calls a function in CheckoutOverlay. This function stores the data sent in the State.
I am trying to simulate what happens when the data is sent to CheckoutOverlay.
The sub component has tests, and, I suppose, I can do something like simulate the click on that component. But that seems like it is more involved than it should be.
Since you have not mentioned what you are trying to test, I am giving you some general suggestions.
You should not test the implementation details, rather test the functionality.
If your state is dependant on the redux store state, you can pass the required data as initialState to your provider.
You cannot use instance on a functional component

Vue Lifecycle: Object is undefined when binding attributes

I seem to be having an issue with the vue lifecycle - the global objects that I'm retrieving data in the DOM using something like {{ family.plusOne }} is defined.
When I'm using it as an attribute such as :checked="family.plusOne" //expecting true as value, it's undefined.
I tried running the :check="callFunction()" and logging it to console.
I get two calls, one saying
family.plusOne is undefined
and another log to console saying
family.plusOne being true
which is the value I expected.
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect" for="switch">
<input type="checkbox" id="switch" #change="setPlusOne($event.target.checked)" class="mdl-switch__input" :checked="(family.plusOne == 1)"/>
<span class="mdl-switch__label" >{{family.plusOne == 1}}</span>
</label>
The {{family.plus ==1 }} within the span displays true but the :checked="(family.plusOne ==1)" is false
First, if you are passing just family.plusOne, what is the result in the child?, undefined?
Secondly, may you can use a computed property like
:checked="computedFamilyPlusOne"
computed: {
computedFamilyPlusOne: {
if(this.family.plusOne == 1){
return true
}else {
return false
}
}
}
My guess is that your family object does not exist as part of the default data binding in the data() {} method that is usually on a Vue.js component. That would mean that before the component is mounted, Vue doesn't know the value when it compiles the template, so it appears as though the value is undefined. Then, at some point, you are probably updating ONLY that property of the family object. This means that the reactive-state of the object has never changed, so Vue.js doesn't know that it needs to recompute the template (reactive "gotcha").
To verify that I am correct, make sure that you use the Vue.set() method, or re-bind a new object with the updated property value for the family object.
I played around with the lifecycle phases
created() {
this.populatePeople();
},
updated() {
componentHandler.upgradeDom();
},
This allowed me to update the data before the DOM was loaded and following some solutions, I call componentHandler.upgradeDom() to show the switches and radio buttons correctly.

NodeJS (gettting error notes.push is not a function)

When I run this code I get push is not a function. I have gone over the code so many times and can't figure out where I went wrong. i have also read many of post and I still can't figure it out. I am new to programming and could use the help.
const fs= require('fs')
const getNotes = function() {
    return 'This just returns get notes'
        
enter code here
};
const addNote  = function (title, body) {
    const notes = loadNotes()
    
    notes.push({
        title: title,
        boby: body
    })
    saveNotes(notes)
    
};
const saveNotes = function (notes) {
    const dataJSON = JSON.stringify(notes)
    fs.writeFileSync('notes.json',dataJSON)
}
// Code below loads the notes. Above, addNote adds the note.
const loadNotes = function () {
    try {
        const dataBuffer = fs.readFileSync('notes.json')
        const dataJSON= dataBuffer.toString()
        return JSON.parse(dataJSON)
    } catch (error) {
        return('Note such file')
    }
    
    
}
module.exports ={
    getNotes: getNotes,
    addNote: addNote
}
So, you have this:
const notes = loadNotes()
notes.push({
title: title,
boby: body
});
If you're getting an error that notes.push is not a function, then that is because loadNotes() is not return an array. That could be for a couple reasons:
JSON.parse(dataJson) successfully parses your json, but its top level object is not an array.
JSON.parse(dataJson) throws and you end up returning a string instead of an array.
You can fairly easily diagnose this by adding a console.log() statement like this:
const notes = loadNotes();
console.log(notes); // see what this shows
notes.push({
title: title,
boby: body
});
FYI, returning a string fromloadNotes()as an error really doesn't make much sense unless you're going to check for a string after calling that function. IMO, it would make more sense to either return null for an error or just let it throw. Both would be simpler and easier to check after calling loadNotes().
And, in either case, you must check for an error return value after calling loadNotes() unless you want loadNotes() to throw upon error like it is.

jquery Validation Engine funcCall not working if only rule

I have an input field that I am trying to add custom validation to (required depending on another field). If I put required AND funcCall() I can see that two errors are returned. If I only put the funcCall nothing is returned. I know it's getting in the function and the condition because I did a console.log() but for some reason it seems like it needs an initial rule to fail to show the error.
Call:
<input type="text" class="validate[funcCall[validatePassportRequired]]" id="form_register_passport_number" value="" name="passport_number" size="50">
Function:
function validatePassportRequired(field, rules, i, options) {
if ($('#register_for').val()!='Local') {
return options.allrules.required.alertText;
}
}
So If I change the Call to:
class="validate[required, funcCall[validatePassportRequired]]"
I get two * This field is required
Do I have to have another validation rule along with the funcCall?
just add the following line before returning the error message and instead of required in returning message put the function name before .alertText.
rules.push('required');
#sunzyflower in your case your function would see like this..
function validatePassportRequired(field, rules, i, options) {
if ($('#register_for').val()!='Local') {
rules.push('required');
return options.allrules.validatePassportRequired.alertText;
}
}
Use
funcCallRequired[validatePassportRequired]
instead of
funcCall[validatePassportRequired]
This will add required internally without having a double message.
If you want more information about the (old) issue :
https://github.com/posabsolute/jQuery-Validation-Engine/issues/392
https://github.com/posabsolute/jQuery-Validation-Engine/pull/785

Resources