I have two arrays. But when one of them is null it gives the following error:
Cannot read property 'toJS' of undefined in that line
Here's the relevant call that triggers the error: {groupsGuney.toJS()}
Here's my declaration of the variables let groupsGuney, groupsKuzey;
And finally here are my two arrays. But when one of them is null it gives the error:
...
if (muso == 1) {
groupsGuney = this.props.groups
.groupBy((group, idx) => idx % maxRows)
.map((ggs, idx) => {
return this.renderGroups(ggs, idx);
}).toList().flatten(true);
}
if (muso == 2) {
groupsKuzey = this.props.groups
.groupBy((group, idx) => idx % maxRows)
.map((ggs, idx) => {
return this.renderGroups(ggs, idx);
}).toList().flatten(true);
}
var result = (
<div>
<div className={classSelector + ' discard-mini-box-area'} >
{ groupsGuney.toJS() }
</div>
<div className={classSelector + ' discard-mini-box-area'} >
{ groupsKuzey.toJS() }
</div>
</div>
);
return result;
}
}
export default DiscardMiniBoxArea;
Instead of doing:
<div>
<div className={classSelector + ' discard-mini-box-area'} >
{groupsGuney.toJS()}
</div>
....
you should do:
<div>
<div className={classSelector + ' discard-mini-box-area'} >
{groupsGuney && groupsGuney.toJS()}
</div>
....
Before calling a function on your object, you need to make sure it's there. If you're uncertain about your object having the function at all times, you will need an additional check, that makes sure toJS is there and that it's a valid function.
If that's the case, update what's inside your container to:
{groupsGuney && typeof groupsGuney.toJS === 'function' && groupsGuney.toJS()}
However, ideally, you would not render at all this specific group if what you would like to render is not there. You should move these checks to before you render your component.
My motivation here is mostly that my call .get of undefined poops itself really hard, and initializing properly all over the place helps, but doesn't catch all edge cases. I just want the data or undefined without any breakage. Specific type checking causes me to do more work later if I want it to make changes.
This looser version solves many more edge cases(most if not all extend type Iterable which has .get, and all data is eventually gotten) than a specific type check does(which usually only saves you when you try to update on the wrong type etc).
/* getValid: Checks for valid ImmutableJS type Iterable
returns valid Iterable, valid Iterable child data, or undefined
Iterable.isIterable(maybeIterable) && maybeIterable.get(['data', key], Map()), becomes
getValid(maybeIterable, ['data', key], Map())
But wait! There's more! As a result:
getValid(maybeIterable) returns the maybeIterable or undefined
and we can still say getValid(maybeIterable, null, Map()) returns the maybeIterable or Map() */
export const getValid = (maybeIterable, path, getInstead) =>
Iterable.isIterable(maybeIterable) && path
? ((typeof path === 'object' && maybeIterable.getIn(path, getInstead)) || maybeIterable.get(path, getInstead))
: Iterable.isIterable(maybeIterable) && maybeIterable || getInstead;
//Here is an untested version that a friend requested. It is slightly easier to grok.
export const getValid = (maybeIterable, path, getInstead) => {
if(valid(maybeIterable)) { // Check if it is valid
if(path) { // Check if it has a key
if(typeof path === 'object') { // Check if it is an 'array'
return maybeIterable.getIn(path, getInstead) // Get your stuff
} else {
maybeIterable.get(path, getInstead) // Get your stuff
}
} else {
return maybeIterable || getInstead; // No key? just return the valid Iterable
}
} else {
return undefined; // Not valid, return undefined, perhaps should return false here
}
}
Just give me what I am asking for or tell me no. Don't explode. I believe underscore does something similar also.
Related
I am getting this error when I am trying to update my state using props basically when my condition matches the flag would certainly go back to its initial state value but it is showing error in this case.
var finalVal;
if (
typeof bigFinalValue === "undefined" ||
bigFinalValue.length < 1 ||
this.props.singleDrag === true
) {
console.log("here he is", this.props.singleDrag);
finalVal = <Content>{task.word}</Content>;
this.props.multiDrag = false;
}
if (
(typeof bigFinalValue === "undefined" || bigFinalValue.length > 1) &&
this.props.multiDrag === true
) {
console.log("bigFinalValue", bigFinalValue);
console.log("selectionCount", selectionCount);
console.log("and here he is again...");
finalVal = <Content>{bigFinalValue}</Content>;
this.props.multiDrag = false;
}
Here the error is pretty obvious. You are trying to set props to false.
this.props.multiDrag = false; //wrong
Props are READ ONLY. You can read the article below to get a better understanding how it works.
https://itnext.io/what-is-props-and-how-to-use-it-in-react-da307f500da0#:~:text=%E2%80%9CProps%E2%80%9D%20is%20a%20special%20keyword,from%20one%20component%20to%20another.&text=Furthermore%2C%20props%20data%20is%20read,be%20changed%20by%20child%20components.
I am trying to implement search bar but it seems it doesn't work.
const [dataCoupons, setDataCoupons] = useState<Coupon[] | undefined>(coupons);
const handleChange = (e: ChangeEvent<HTMLInputElement> & { length: number }) => {
let couponsFilter = dataCoupons;
if (e.length > 0) {
Object.keys(e).forEach((k) => {
if (e[k].value === 0) {
couponsFilter = couponsFilter
?.slice()
.filter((x) => x.durationType.localeCompare('ONCE') === 0);
}
if (e[k].value === 3) {
couponsFilter = couponsFilter?.slice().filter((x) => x.valid === true);
}
if (e[k].value === 4) {
couponsFilter = couponsFilter?.slice().filter((x) => x.valid === false);
}
});
} else {
couponsFilter = coupons;
}
setDataCoupons(couponsFilter);
};
<Select
onChange={handleChange}
isMulti
options={options}
isClearable={isClearable}
classNamePrefix='select'
/>
I have an error message for each e[k]
What am i missing ?
There are two main things stopping you from getting value.
You're protecting with if (e.length > 0) {}
e does not normally have length property because it is an object. If you watched closely, TypeScript does tell you that. It is why you had to add & { length: number } to stop TypeScript from complaining.
If you were to do something like below (without the above mentioned protection)
Object.keys(e).forEach((k) => { console.log(k) })
And then went and triggered change event, you would be able to observe that the console is printing out string keys of all the properties that are attached to e object directly.
One of those properties is target property. You are most likely after that property. Going along the lines of your thinking (how you wrote your code), you would most likely need something like below:
Object.keys(e).forEach((k) => {
if (k === "target") {
console.log(e[k].value);
}
});
The above will capture value from the input field.
I have to warn you though that it seems like a very unsustainable way of creating forms and getting their values. It would be probably best to read this before you proceed.
Also, here's Sandbox to see it in action in most simple implementation.
I was making confirmation when the user tried to close the form by modified and values length > 0.
if (modified) {
return (
Object.keys(modified).filter(
(modifiedItem) => modified[modifiedItem] && values[modifiedItem]?.length > 0,
).length > 0
)
}
Everything is working fine until there are values with an array:
when I try to access by values[answers.0.icon] there is undefined, of course, it should be accessed by values.answers[0].icon, by is it possible to do it when iterating modified keys? Or another way should be appreciated.
Thank you beforehand.
Below screenshots of values:
Modified keys:
I'd suggest to include lodash and use the get function. This will resolve the "path" for you.
For example _.get(values, modifiedItem).
More info can be found at https://lodash.com/docs/4.17.15#get
you could add undefined and null in the if statement, to check if it's true and not undefined and not null before it filter else it will be null or you can put something else.
if (modified && modified !== undefined && modified !== null) {
return (
Object.keys(modified).filter(
(modifiedItem) => modified[modifiedItem] && values[modifiedItem]?.length > 0,
).length > 0
)
}
else {
null
}
You can perhaps check for such situation if its an array and treat it differently.
I agree with solution provided by #Stijn answer, however if you dont wanna carry unnecessary baggage of Lodash you can use below code.
const parseDeep = (obj, path, def) => (() => typeof path === 'string' ?
path.replace(/\[(\d+)]/g,'.$1') : path.join('.'))()
.split('.')
.filter(Boolean)
.every(step => ((obj = obj[step]) !== undefined)) ? obj : def
if (modified) {
return (
Object.keys(modified).filter(
(modifiedItem) =>
Array.isArray(modifiedItem) ?
modified[modifiedItem] && parseDeep(values, modifiedItem, false) : //modify as required
modified[modifiedItem] && values[modifiedItem]?.length > 0,
).length > 0
)
}
when the search value is changed, the state does not change, although when the search value is reduced, the changes occur instantly
this is one code in order*
if(prop.props.statePokemon){
prop.props.setStatePokemon(false)
why the given value does not change:
setPokemon(saveDataPokemon) // the value does not change
but all other logs are going fine:
let rangePokemonFromAttack:(IPokemon | undefined | any)[] = allPokemon.data.map((pokemon: IPokemon) => {
if(prop.props.rangeAttack.rangeAttackFrom <= pokemon.stats[1].base_stat && pokemon.stats[1].base_stat <= prop.props.rangeAttack.rangeAttackTo){
return pokemon
}
}).filter((pokemon: IPokemon | undefined) => {
return pokemon !== undefined
})
console.log(allPokemon,'all',
saveDataPokemon, 'save',
rangePokemonFromAttack ,'range')
if(typeof rangePokemonFromAttack[0] !== 'undefined'){
setPokemon(saveDataPokemon)
setPokemon({data: rangePokemonFromAttack})
}else{
setPokemon(saveDataPokemon)
}
}
prop.props.rangeAttack.rangeAttackFrom = 0
prop.props.rangeAttack.rangeAttackTo = 400
}
The state variables doesn't change like that you need to use setState() function for this purpose, which in turn calls the render again. For more info Google setState or visit this link https://reactjs.org/docs/react-component.html In this docs search setState function
I made a mistake and caused another state
prop.props.setStatePokemon(false)
let rangePokemonFromAttack:IPokemon[] = saveDataPokemon.data.filter((pokemon: IPokemon) => {
if(prop.props.rangeAttack.rangeAttackFrom <= pokemon.stats[1].base_stat
&& pokemon.stats[1].base_stat
<= prop.props.rangeAttack.rangeAttackTo){
return pokemon
}
})
if(typeof rangePokemonFromAttack[0] !== 'undefined'){
setPokemon({data: rangePokemonFromAttack})
}else{
setPokemon(saveDataPokemon)
}
Use multiple Map on array. I get error:
SyntaxError: C:\Users\Laptop15\Desktop\React Native\src\screens\Question.js: Unexpected token, expected "," (59:7)
I use function that: {PytaniePush(quizDane.quest1)}
function PytaniePush(myID) {
if(quizDane && quizDane.quest1 && myID){
myID.map((item, key)=>(
myID[key].map((item2, key2)=>(
return ({RadioPush(myID[key].item2)});
));
));
}
}
I want to console log with all elements in array and object:
quest1->array[Object(A,B), Object(A,B)]
Data look: that
I want to get:
A in 0 is ...
B in 0 is ...
A in 1 is ...
B in 1 is ...
You have an syntax error in your code. Here is right code.
function PytaniePush(myID) {
if (quizDane && quizDane.quest1 && myID) {
myID.map((item, key) =>
myID[key].map((item2, key2) => {
return RadioPush(myID[key].item2);
})
);
}
}
Next time when you will have a syntax error try to use Prettier to find error and improve format of your code.
There are some syntax errors in your code. Try this one.
function PytaniePush(myID) {
if(quizDane && quizDane.quest1 && myID){
myID.map((item, key) => myID[key].map((item2, key2) => {
return RadioPush(myID[key].item2);
} ));
}
}
Try to use an ES6 aware IDE. That way you will not stumble upon this kind of issues.