How to use variable inside if from same function? - reactjs

Now I would like to get a variable from if inside same function as if like below.
renderItemBox() {
const { store } = this.props;
const currentScreen = this.props.navigation.state.routeName;
AsyncStorage.getItem('openingGenre')
.then((openingGenreValue) => {
if (currentScreen === 'EachShopGenreScreen') {
if (openingGenreValue === 'food') {
const items = this.store.restourantStore.Items;
} else {
Alert.alert('予期せぬ不具合が発生いたしました。再度お試し下さい');
}
});
return items.map((value, index) => (
//////
)
However, this code is not working, I cannot get "items" from IF on items.map~~~~
Why this is happening?
Could someone help me.

You need to declare items using let as an empty array in the function scope then do your if statement.
Or at least that's one way of doing it.
Btw this is more of a JavaScript question.

Related

React : Pushing result of map() to an array

Hello I am trying to map through an array of objects and push them to a new array.
My ISSUE : only the last item of the object is being pushed to the new array
I believe this has to do with React life cycle methods but I don't know where I should I loop and push the values to the array to get the full list
//My object in an array named states
var states = [{"_id":"Virginia","name":"Virginia","abbreviation":"VN","__v":0},{"_id":"North Carolina","name":"North Carolina","abbreviation":"NC","__v":0},{"_id":"California","name":"California","abbreviation":"CA","__v":0}];
export function StateSelect()
{
**EDIT 1**
const options = [];
function getStates()
{
//This is how I am looping through it and adding to an array
{ states.length > 0 &&
states.map(item =>
(
console.log(`ITEM: ${JSON.stringify(item)}`),
options.push([{ value: `${item.name}`, label: `${item.name}`}])
))
}
}
return( {getStates()}: );
}
Thank you
It looks like your getStates() might not even be returning anything... but assuming it is, I believe you should be able to accomplish this using a forEach() fn in order to push values into your options array... Try adding the following into your map:
states.map((item) => {
console.log(`ITEM: ${JSON.stringify(item)}`);
let processed = 0;
item.forEach((i) => {
options.push([{ value: `${i.name}`, label: `${i.name}`}]);
processed++;
if(processed === item.length) {
// callback fn, or return
}
}
.map usually used to return another result, you could just use .forEach
In fact, you don't really need to declare options at all, just use .map on state to return the result would be fine.
return states.length > 0 && states.map(({ name }) => {
return { value: name, label: name };
});

Not able to state with react typed.js callbacks

I'm trying to update a counter located in the state every time the type string changes with this node module. When I'm attaching the preStringTyped function to the component, the function (the alert located in the preStringTyped) triggers only once.
Here's the module: https://github.com/ssbeefeater/react-typed
Here's my code - you can ignore the randomlySelectElements and the displayTweets function, what matters here is the preStringTyped and what is inside the return().
preStringTyped = () => {
alert("typed")
}
randomlySelectElements = (number, array) => {
let shuffedArray = _.shuffle(array);
let selectedEle = shuffedArray.slice(0, number);
return selectedEle;
}
displayTweets = () => {
if(!this.state.rawData){
return null
}else{
let getRandomTweetsStrings = () => {
return this.randomlySelectElements(10, this.state.rawData)
.map((ele, index) => {
return ele.masterData.randomString
})
}
return (
<ReactTyped
loop
typeSpeed={50}
backSpeed={20}
strings={
getRandomTweetsStrings()
}
smartBackspace
backDelay={1}
fadeOutDelay={100}
loopCount={0}
showCursor
cursorChar="|"
onBegin={this.preStringTyped()}
/>
)
}
}
First you need to use preStringTyped callback (not onBegin) that will be triggered before each string is typed. Also in your code you emidiatly execute the function this.preStringTyped() but you should pass it as a reference to the callback property (preStringTyped={this.preStringTyped}). Your code should be like this
<ReactTyped
loop
typeSpeed={50}
backSpeed={20}
strings={
getRandomTweetsStrings()
}
smartBackspace
backDelay={1}
fadeOutDelay={100}
loopCount={0}
showCursor
cursorChar="|"
preStringTyped={this.preStringTyped} // <- not onBegin={this.preStringTyped()}
/>

Can anyone explain why my state is getting updated even when i dont set it manually

So I just spent an hour debugging this code and finally got it to work, but I would want to know why this happened in the first place. I have a function that takes a value from my state, operates on it and saves the output in another variable in the state. This is the fuction:
getFolderNames = async () => {
const promises = this.state.rows.map(async item => {
if (item[".tag"] == "folder" && item.name.length > 20) {
item.name = await getFolderName(item.name);
return item;
} else return item;
});
const result = await Promise.all(promises);
this.setState({
rowsToDisplay: result
});
};
when i run this function, it was updating both the rows and rowsToDisplay to the result variable when i was only calling setState on only one of them.
Changing the function as below solves the issue but I would like to know why.
getFolderNames = async () => {
const promises = this.state.rows.map(async item => {
if (item[".tag"] == "folder" && item.name.length > 20) {
let item2 = {
...item
};
item2.name = await getFolderName(item.name);
return item2;
} else return item;
});
const result = await Promise.all(promises);
this.setState({
rowsToDisplay: result
});
};
It's because of how JavaScript handles variables. When you set a variable to an array or object, it doesn't make a new object but rather just references the original array/object.
As such, if you set a variable to equal some object, and then set a property of that variable, the original object will also be updated. Check this snippet for an example.
var foo = {changed: false};
var bar = foo;
bar.changed = true;
console.log("foo", foo.changed)
console.log("bar", bar.changed)
You can read more about the subject here: https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0
I hope this helps you in the future, since I know I also spent many hours banging my head against exactly the sort of cases you described in your original question.

Looping within const in ReactJS

This is really minimal... but I haven't been able to figure this out.
const compose_url = (id, key) =>
`${id}/image/_/${key}`;
const get_images = compose_url(
this.props.dataset_id, // pass in prefix (2018_1_25)
get_image_arrays // This returns an array with two arrays e.g. [["img1.png"], ["img2.png"]]
);
I want this to return "2018_1-25/img1.png" and "2018_1-25/img2.png", but I'm only getting that for the first array, ("2018_1-25/img1.png") not for the second one. How could I loop through this to add the prefix to both images?
Please help... I haven't found documentation or examples on how to do this.
You need to update compose_url() function here, and make sure you always pass array as second of the vairable.
const compose_url = (date, imageArray) =>
imageArray.map((eachImage) => `${id}/image/_/${eachImage}`);
hope this helps.
const get_images = [];
const { dataset_id: id } = this.props;
get_images_array.forEach(arr => {
arr.forEach(path => {
get_images.push(
compose_url(
id,
path
)
);
}
});
EDIT:
I took a different approach to other answers and instead of modifying the compose_url method, I worked off of the the given data. This approach iterates over the top level array (get_images_array) and then iterates over each of the arrays in get_images_array. For each path in the inner arrays, the result of compose_url is pushed onto the get_images result array.
try this.
const compose_url = (id, arr) => {
return arr.map((ar) => (
`${id}/image/_/${ar}`
));
};
This function will return [ "2018_1_25/image/_/img1.png", "2018_1_25/image/_/img2.png" ]
You can simply map over the array like
const compose_url = (id, arr) => {
return [].concat(arr.map(data => [].concat(data.map(key) => `${id}/${key}`)));
}
const get_images = compose_url(
this.props.dataset_id, // pass in prefix (2018_1_25)
get_image_arrays // This returns an array with two arrays e.g. [["img1.png"], ["img2.png"]]
);

Searching JSON array using another JSON array node js

I'm trying to filter a JSON array using another JSON array criteria that I have using (filter).
Here is my code:
function filterArray(object, criteria){
return object.filter(function(obj){
for(var i=0;i<criteria.length;i++){
let criteriaEle = criteria[i];
return Object.keys(criteriaEle).forEach(function(key){
if(obj[key] == criteriaEle[key]){
return obj;
}
})
}
})
}
For example:
object = [{type:1,company:1,color:0,name:a},{type:2,company:1,color:0,name:b},{type:1,company:3,color:0,name:c},{type:4,company:1,color:0,name:d},{type:1,company:1,color:1,name:e}]
criteria = [{type:1,company:1,color:0},{type:1,company:1,color:1}]
So if I give these two arrays to the function it should return
obj = [{{type:1,company:1,color:0,name:a},{type:1,company:1,color:1,name:e}}]
I'm not sure where am I going wrong in this. Please help.
Update:
Also, I do not want to use obj.type or obj.company or object.color as parameters to search as I want to make my code maintainable and do not want to come and update it later if in future more criteria's are added.
const data = [{type:1,company:1,color:0,name:'a'},{type:2,company:1,color:0,name:'b'},{type:1,company:3,color:0,name:'c'},{type:4,company:1,color:0,name:'d'},{type:1,company:1,color:1,name:'e'}];
const criteria = [{type:1,company:1,color:0},{type:1,company:1,color:1}];
function checkCriteria(obj) {
return criteria.some(criterion => {
for (const key in criterion) {
if (criterion[key] !== obj[key]) {
return false;
}
}
return true;
});
}
const filtered = data.filter(checkCriteria);
console.log('Filtered array: ', filtered);
Here is one solution.
Here are some references
Array.some
Array.filter
Based on the comment, adding another snippet to explain the concept of closures.
const data = [{type:1,company:1,color:0,name:'a'},{type:2,company:1,color:0,name:'b'},{type:1,company:3,color:0,name:'c'},{type:4,company:1,color:0,name:'d'},{type:1,company:1,color:1,name:'e'}];
function createCriteriaValidationFunction(criteria) {
return function checkCriteria(obj) {
return criteria.some(criterion => {
for (const key in criterion) {
if (criterion[key] !== obj[key]) {
return false;
}
}
return true;
});
}
}
const criteria = [{type:1,company:1,color:0},{type:1,company:1,color:1}];
const filtered = data.filter(createCriteriaValidationFunction(criteria));
console.log('Filtered array: ', filtered);
It's the same concept as before, however, criteria was defined in the file. This time, criteria can be defined outside and can be passed in to the function. The trick is to create the checkCriteria function on the fly with criteria passed in and available in the closure. In both cases, criteria variable is available in the scope in which checkCriteria is executed.

Resources