So, I was working with React Native and found a very silly problem which I can't seem to get my head around. I have declared an array of objects (storeVar here) with some hardcoded value. When I try to loop through it using the javascript map function I get only the value only at the first index. The code is below -
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TextInput,
ScrollView,
AsyncStorage,
TouchableOpacity
} from 'react-native';
import Note from './note.js'
// -------------------------------------------------------------------------
const storeVar = [
{
'd' : '',
'n' : 'Hello'
},
{
'd' : '',
'n' : 'Awesome'
},
];
export default class reactNativePractise extends Component {
constructor(props) {
super(props);
this.state = {
noteArray : [
{
'date' : '',
'note' : ''
}
],
};
}
componentDidMount() { this.onLoad(); }
onLoad = async()=> {
storeVar.map(async(value, index) => {
try {
var d = new Date();
// const storedVal = [await AsyncStorage.getItem(storeVar[index].n)];
alert("Key is : " + JSON.stringify(storeVar[index-1].n, null, 4));
// this.state.noteArray.push( {date :d.getFullYear() + "/" + (d.getMonth()+1) + "/" + d.getDate(), note : storedVal[index]} );
}
catch(error) { alert('Error' + error) }
});
}
Only Hello is displayed and not the text Awesome. Any help would be greatly appreciated.
Don't use index-1, use
JSON.stringify(storeVar[index].n, null, 4));
that index will start from 0, so doing -1 of 0 will result to -1, and it will fail to access -1th element of array, when index becomes 1 and 1 - 1 will be 0 at that time its printing the Hello (0th index element).
Related
I'm new here on the site, I have a question regarding a function in react that I am unable to resolve. The solution is very simple but it does not work for me.
I build a social network in React, in the social network I have users, each user has a different name, it's like a key.
I have a match object, which contains matches between one user, represented by handle, and the other users represented by match_(number).
Because each of the users' names is unique, I want to use them in the key.
The problem is that for each user the name of the atribute is different, and I can not think of a way, to be able to access in a loop for all users.
match =
[
{handle: "backend4" , ...},
{match_1: "backend1" , ...},
{match_2: "backend2" , ...},
{match_3: "backend3" , ...},
{match_4: "devops1" , ...},
{match_5: "devops2" , ...},
{match_6: "mobile2" , ...},
{match_7: "test500" , ...},
{match_8: "testing100" , ...},
{match_9: "testing200" , ...},
{match_10: "testtttttt" , ...},
];
recentMatchesMarkup = match.map((singleMatch) =>
<Match key={singleMatch.id} matchInfo={singleMatch} />)
);
I'm sure the problem is very small, but I can 't think of how to deal with it
Here is how you could access the value of match_x, x being the index of the loop :
match.map((el, i) => console.log(el[match_${i}]))
(There is the special quote wrapping match_${i} above. I just can't display it since they are used to display code.. see this link if you don't know about it).
But note that is only works with a key match_x so if you are 100% sure it's ok for you, go for it.
The first key handle won't be displayed (return undefined) so you might need to add a condition to display your <Match> component.
To be sure each match correspond to the index, here is an example on Stackblitz about how you could do it, and here is the code :
import React, { Component } from "react";
import { render } from "react-dom";
import "./style.css";
const App = () => {
const [sortedMatch, setSortedMatch] = React.useState([]);
const match = [
{ handle: "backend4" },
{ match_2: "backend2" },
{ match_3: "backend3" },
{ match_1: "backend1", test: "text" },
{ match_4: "devops1" },
{ match_5: "devops2" },
{ match_6: "mobile2" },
{ match_7: "test500" },
{ match_8: "testing100" },
{ match_9: "testing200" },
{ match_10: "testtttttt" }
];
React.useEffect(() => {
const matchByIndex = [];
match.forEach(el => {
const key = Object.keys(el).find(k => k.includes("match"));
if (key) {
let nb = key.split("_");
nb = nb[nb.length - 1];
matchByIndex[nb] = el;
}
});
setSortedMatch(matchByIndex);
}, []);
if (!sortedMatch.length) return <>Loading...</>;
return (
<div>
{sortedMatch.map((el, i) => (
<>
{el[`match_${i}`]}
<br />
</>
))}
</div>
);
};
render(<App />, document.getElementById("root"));
Link: codesandbox
I'm having the following problem can anyone help me out?
Error:
Cannot read property 'getJsonFromDiff' of undefined
-> let outStr = Diff2Html.getJsonFromDiff(dd, {
CodeDiff.js:
import React, { Component } from "react";
import PropTypes from "prop-types";
import { createPatch } from "diff";
import { Diff2Html } from "diff2html";
import { InlineMath } from "react-katex/dist/react-katex";
import "highlight.js/styles/googlecode.css";
import "diff2html/lib/diff2html";
function CodeDiff(props) {
const { oldStr, newStr, context, outputFormat } = props;
const createdHtml = (oldString, newString, context, outputFormat) => {
function hljs(html) {
return html.replace(
/<span class="d2h-code-line-ctn">(.+?)<\/span>/g,
'<span class="d2h-code-line-ctn"><code>$1</code></span>'
);
}
let args = [
"",
oldString || "",
newString || "",
"",
"",
{ context: context }
];
let dd = createPatch(...args);
let outStr = Diff2Html.getJsonFromDiff(dd, {
inputFormat: "diff",
outputFormat: outputFormat,
showFiles: false,
matching: "lines"
});
let html = Diff2Html.getPrettyHtml(outStr, {
inputFormat: "json",
outputFormat: outputFormat,
showFiles: false,
matching: "lines"
});
return hljs(html);
};
const html = () => createdHtml(oldStr, newStr, context, outputFormat);
return (
<div id="code-diff" dangerouslySetInnerHTML={{ __html: html() }}></div>
);
}
CodeDiff.propTypes = {
oldStr: PropTypes.string.isRequired,
newStr: PropTypes.string.isRequired,
context: PropTypes.number,
outputFormat: PropTypes.string
};
CodeDiff.defaultProps = {
oldStr: "",
newStr: "",
context: 5,
outputFormat: "line-by-line"
};
export default CodeDiff;
Well, "diff2html" library exposes only "html" and "parse" functions, so in order to use it from single object Diff2Html like you want you have to import it diffrently, like so:
import * as Diff2Html from "diff2html";
But then there are no such things there as getJsonFromDiff and getPrettyHtml
Not sure where you got those from, getJsonFromDiff is actually a test name in their github - https://github.com/rtfpessoa/diff2html/search?q=getJsonFromDiff
But it is not a function. And there is not at all such thing as getPrettyHtml
So i suppose you wanted to use parse (instead of getJsonFromDiff) and html (instead of getPrettyHtml) that way it works fine as far as i can tell - https://codesandbox.io/s/material-demo-forked-jhljq?file=/CodeDiff.js:114-153
I had the same question, I was able to get access to these functions like this:
import * as Diff2HtmlLib from 'diff2html';
Diff2HtmlLib.Diff2Html.getJsonFromDiff(diff, diffOptions)
I'm trying to create a ReactDataGrid and I'm getting this error when I use rowGetter. The grid works fine when I use rows={myData} though, and I really don't understand what is happening.
Here's my code :
import React, {Component, useState } from 'react';
import DataGrid from 'react-data-grid';
import 'react-data-grid/dist/react-data-grid.css';
import { Toolbar, Data, Filters } from "react-data-grid-addons";
const {
NumericFilter
} = Filters;
const selectors = Data.Selectors;
class YvideoList extends Component {
constructor(props, context){
super (props, context);
const selectors = Data.Selectors;
const defaultColumnProperties = {
filterable: true,
// width: 160
};
this.colums = [
{ key: 'title', name: 'Title' },
{ key: 'views', name: 'Views', filterRenderer: NumericFilter },
{ key: 'date', name: 'Date' }]
.map(c => ({ ...c, ...defaultColumnProperties }));
}
rowGetter = (index) => {
console.log("INDEX: ", index);
return selectors.getRows(this.props.videos[0].results)[index];
};
rowsCount = () => {
return selectors.getRows(this.props.videos[0].results).length;
};
render() {
return (
<DataGrid
columns={this.colums}
rowGetter={this.rowGetter} // -> GRID CRASHES
rowsCount={2}
//rows={this.props.videos[0].results} // -> THIS WORKS
/>
)
}
}
export default YvideoList;
The error I'm getting is the following :
TypeError: undefined is not an object (evaluating 'rows.length')
DataGrid
src/DataGrid.tsx:268
265 | lastFrozenColumnIndex={columnMetrics.lastFrozenColumnIndex}
266 | draggableHeaderCell={props.draggableHeaderCell}
267 | onHeaderDrop={props.onHeaderDrop}
> 268 | allRowsSelected={selectedRows?.size === rows.length}
| ^ 269 | onSelectedRowsChange={onSelectedRowsChange}
270 | sortColumn={props.sortColumn}
271 | sortDirection={props.sortDirection}
Any help appreciated ! Just note that the console.log from the function rowGetter is never shown in the console, so the grid dies before that.
EDIT1:
I think the problem lies in the version I'm using of the data grid. In version 5.0.4 the code I added looks like working, but not on version 7.
Unfortunately I can't find examples of filtering/sorting for version 7-canary
So I found out the reason and it was caused by version change from the react-data-grid, they dropped the rowgetters so I was using it wrong, the documentation is not up to date on their website which is a pity because the grid looks really good.
For actually demos you can check here :
https://github.com/adazzle/react-data-grid/tree/canary/stories/demos
I'm trying to convert strings starting with '#' and '#' to a clickable link and for that I'm doing a regex to replace that word with html tag and adding onclick function inside it to perform the operation by calling the search function. I'm using 'html-react-parser' to parse that in the render part. That is converting the text to button but it is not calling the search() function when I click it on. I can't understand how can I fix that? Is there anyway to fix that or any better approach?
The data I'm trying to convert is in JSON format which has three different field.
Data sample:
{date:"2014-06-01 04:27:08", text:"Bob Newhart, Master of the One-Sided Conversation t.co/xmdtl25WyD via #nytnow", user_id:"nytimes"}
My code:
import React, { Component } from 'react';
import client from './Credentials';
import '../App.css';
import Linkify from 'react-linkify';
import Parser from 'html-react-parser';
export default class Search extends Component {
constructor(props) {
super(props);
this.state = {results: []};
}
// const Autolinker = require( 'autolinker' );
search(string){
client.search({
index: 'tweet',
type: 'tweet',
size: 1000,
body: {
query: {
"bool": {
"should": [
{"match": {"text": string}},
{"match": {"user_id": string}},
{"match": {"date": string}}
]
}
},
}
}, (error, response, status) => {
if (error) {
console.log("search error: " + error)
}
else {
console.log("--- Response ---");
console.log(response);
console.log("--- Hits ---");
response.hits.hits.forEach(function (hit) {
let re1 = new RegExp("((#|#)([a-z0-9]+))", "g");
hit._source.text = hit._source.text.replace(re1, ("<button onclick={this.search($&)}>$&</button>"));
this.setState({results: this.state.results.concat([hit._source])})
}.bind(this)
);
}
// console.log(this.state.results);
})
}
handleKeyPress = (event) => {
if(event.key === 'Enter'){
event.preventDefault();
const search_query = event.target.value;
this.state.results=[];
this.search(search_query);
}
};
render() {
return(
<Linkify>
<div>
<input className={"search-bar"} type="text" onKeyPress={this.handleKeyPress.bind(this)}>
</input>
<div>{this.state.results.map((results, index) => (
<p key={index} className={"result"}><span className={"date"}>{results.date}</span> <span> </span>
<span className={"user_id"}>{results.user_id}</span> <span> </span>
<span>{Parser(results.text)}</span></p>
))}</div>
</div>
</Linkify>
);
}
}
From what I see, you are trying to parse string as javascript code. This isn't normally possible, and is considered dangerous. If you want to do so, this issue has some insights
change the button to
hit._source.text = hit._source.text.replace(re1, ("" + $& + ""));
Parser(results, { transform: () => this.htmlParserTransformer })
and
import {convertNodeToElement} from "react-html-parser"
htmlParserTransform = (node, index) => {
if (node.type == "tag" && node.name == "button") { // button tag
const {id} = node.attribs // extract the actual url
return (
<button
onClick={() => this.search(id)} // click
>
{convertNodeToElement (node, index, this.htmlParserTransform)}
</span>
</a>
)
}
PS: this code isn't tested, but I hope I'm pointing you in the right direction.
I am creating a shopping cart in Angular 4 and want to check if a new product prod yet exists in the cartProducts array.
Here's my Component:
Component
import { Component, OnInit } from '#angular/core';
import { Router } from "#angular/router";
import { ProductsService } from '../service/products.service';
#Component({
selector: 'app-store',
templateUrl: './store.component.html',
styleUrls: ['./store.component.css']
})
export class StoreComponent implements OnInit {
itemCount: number;
cartProducts: any = [];
productsList = [];
constructor( private _products: ProductsService ) { }
ngOnInit() {
this.itemCount = this.cartProducts.length;
this._products.product.subscribe(res => this.cartProducts = res);
this._products.updateProducts(this.cartProducts);
this._products.getProducts().subscribe(data => this.productsList = data);
}
addToCart(prod){
this.cartProducts.hasOwnProperty(prod.id) ? console.log("Added yet!") : this.cartProducts.push(prod);
console.log(this.cartProducts)
}
}
My addToCart function which is fired by click works fine, but only from second time.
1 click - we add a product in the empty cartProducts array, the product is added
2 click - although the product is added, it is added again and there are two same products in the array now. I've got the array with the two same products.
3 click - console shows "Added yet!", now it recognizes that the product is in the array yet.
UPD
The product is an object of type:
{
"id" : "1",
"title" : "Title 1",
"color" : "white"
}
How to fix the issue?
hasOwnProperty is for checking if a key exists in an object, you're using it for an array. Use this instead:
addToCart(prod){
this.cartProducts.indexOf(prod) > -1 ? console.log("Added yet!") : this.cartProducts.push(prod);
console.log(this.cartProducts)
}
try this :
let idx = this.cartProducts.findIndex(elem => {
return prod === elem
})
if (idx !== -1) {
console.log("Added yet!")
} else {
this.cartProducts.push(prod);
}