I need to generate an array of 10 items and this is the code I have to use.
for (let i = 0; i < 10; i++) {
vehicles.push({
manufacturer: faker.vehicle.manufacturer(),
model: faker.vehicle.model(),
type: faker.vehicle.type(),
fuel: faker.vehicle.fuel(),
vin: faker.vehicle.vin(),
color: faker.vehicle.color()
})
}
My question is how do I use it? So far I have this:
import React from 'react';
import Stack from 'react-bootstrap/Stack'
import VehicleActions from './VehicleActions';
import VehicleList from './VehicleList';
import Vehicle from './Vehicle';
class App extends React.Component {
constructor(props) {
super(props);
this.state = { vehicles: [] };
this.onNewContact = this.onNewContact.bind(this);
this.handleContactSelected = this.handleContactSelected.bind(this)
this.handleDeleteContact = this.handleDeleteContact.bind(this)
}
onNewContact(vehicle) {
this.setState((state) => {
return {
vehicles: state.vehicles.concat(vehicle)
}
})
}
handleContactSelected(manufacturer) {
this.setState((state) => {
return {
selected: manufacturer
}
})
}
handleDeleteContact(manufacturer) {
this.setState((state) => {
return {
vehicles: state.vehicles.filter((vehicle) => vehicle.manufacturer !== manufacturer),
selected: null
}
})
}
handleGenerateVehicle() {
this.props.onNewContact(this.generateContact())
}
render() {
return (
<Stack gap={3} className="col-md-10 mx-auto">
<VehicleActions onNewContact={this.onNewContact}
selectedContact={this.state.selected} />
<Vehicle />
<VehicleList vehicles={this.state.vehicles}
onContactSelected = {this.handleContactSelected}/>
</Stack>
)
}
}
export default App
I'm using the "npm install react-bootstrap bootstrap #faker-js/faker" to generate the random text, I have tested it in the alert or console log and it works, but I have no clue where to insert it so the 10 values are shown in a column.
If you want to hardcode the list of vehicles (I assume that is what you are supposed to do), just put the code in the constructor:
class App extends React.Component {
constructor(props) {
super(props);
let vehicles = [];
for (let i = 0; i < 10; i++) {
vehicles.push({
manufacturer: faker.vehicle.manufacturer(),
model: faker.vehicle.model(),
type: faker.vehicle.type(),
fuel: faker.vehicle.fuel(),
vin: faker.vehicle.vin(),
color: faker.vehicle.color()
})
}
this.state = { vehicles };
this.onNewContact = this.onNewContact.bind(this);
this.handleContactSelected = this.handleContactSelected.bind(this)
this.handleDeleteContact = this.handleDeleteContact.bind(this)
}
// ...
}
Related
I'm trying to pass value from one component to another. First one looks like this:
class ListStation extends Component {
constructor(props) {
super(props)
this.state = {
stations: []
}
this.editStation = this.editStation.bind(this);
}
editStation(id) {
this.props.history.push(`/add-station/${id}`);
}
componentDidMount() {
StationService.getStations().then((res) => {
this.setState({ stations: res.data });
})
}
}
render() {
return (
<div>
<tbody>
{this.state.stations.map(
station =>
<tr key={station.id}>
<td>{station.city}</td>
<td>{station.name}</td>
<td>
<button onClick={() => this.editStation(station.id)} className="btn btn-info">Modify</button>
...
</div>
</div>
);
}
}
export default ListStation;
And another looks like this:
import React, { Component } from 'react';
import StationService from '../services/StationService';
class CreateStationComponent extends Component {
constructor(props) {
super(props)
this.state = {
station: {
id: this.props.match.params.id,
city: '',
name: '',
trains: [
{
number: '',
numberOfCarriages: ''
}
]
}
}
this.changeCityHandles = this.changeCityHandles.bind(this);
this.changeNameHandles = this.changeNameHandles.bind(this);
this.saveStation = this.saveStation.bind(this);
}
componentDidMount() {
if (this.state.station[0].id === '_add') {
return;
} else {
StationService.getStationById(this.state.id).then((res) => {
let station = res.data;
this.setState({ name: station[0].name, city: station[0].city })
});
}
console.log(this.state.station.city + 'dfddddd');
}
But when I try to pass value from one component to another I get error: Property of undefined. The response I get from API looks like this:
I'm trying to edit values based on the id taken from the first component but it seems to fail.
if (this.state.station[0].id === '_add') {
return;
}
Have a look at this if statement from your codebase I think you should remove [0] after this.state.station ... this is because station is an object not an Array
Change it to if (this.state.station.id === '_add') {
I'm building a help page with Gatsby and have a search bar (Searchbar.js) where I'm trying to pass the user's input in the field (search bar is always present within the page--think like Evernote's help page) to a component that conducts the search (search.js), which then passes that output to the actual results page (SearchResults.js).
When I do gatsby develop everything works as it should, but when I do a gatsby build I get an error where it says it cant read the property "query" because its undefined (line 63 of search.js: var search = location.state.query.trim()). Why is this failing on build?
Searchbar.js
import React from 'react'
import { navigate } from 'gatsby'
import { FaSearch } from 'react-icons/fa'
import searchbarStyles from "./searchbar.module.css"
export default class Search extends React.Component {
constructor(props) {
super(props)
this.state = {
search: ''
}
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleSubmit(event) {
event.preventDefault()
var query = this.state.search
navigate(
"/search/",
{
state: { query },
}
)
}
handleChange(event) {
this.setState({
search: event.target.value
})
}
render(){
return (
<div className={searchbarStyles.global_search}>
<div className={searchbarStyles.row}>
<form className={searchbarStyles.search} onSubmit={this.handleSubmit}>
<input
type='text'
id='globalSearchInput'
className=''
placeholder='Search Help & Training'
autoComplete='off'
value={this.state.search}
onChange={this.handleChange}
/>
<button
type='submit'
disabled={!this.state.search}
><FaSearch className={searchbarStyles.searchIcon}/></button>
</form>
</div>
</div>
)
}
}
search.js
import React, { useMemo } from 'react'
import Layout from '../components/Layout'
import SearchResults from '../components/SearchResults'
import { graphql } from 'gatsby'
import Fuse from 'fuse.js'
const matchThreshold = .65
//options for the fuzzy search
var fuseOptions = {
shouldSort: true,
threshold: matchThreshold,
location: 0,
distance: 99999999999,
minMatchCharLength: 1,
includeMatches: true,
includeScore: true,
keys: [
{name: "title", weight: 0.3 },
{name: "content", weight: 0.7}
]
};
function cleanString(string) {
const re = /( |<([^>]+)>)/ig
return string.replace(re,'')
}
function FuzzySearch (query, data) {
fuseOptions.minMatchCharLength = query.length
var dataPrepped = data.map(function(element) {
return {
"title": element.node.frontmatter.title,
"content": cleanString(element.node.html),
"slug": element.node.fields.slug,
}
})
var fuse = useMemo(() => new Fuse(dataPrepped, fuseOptions), [])
var results = fuse.search(query)
//customize the results to only return matches within desired threshold
return results.filter(function(match) {
if(match.score <= matchThreshold) {
return true
}
return false
}).map(function(match) {
return {
"title": match.item.title,
"slug": match.item.slug,
"matches": match.matches
}
})
}
export default ({ location, data }) => {
console.log("SERACH.JS\n")
console.log(JSON.stringify(location))
var search = location.state.query.trim()
var results = []
if(search.length) results = FuzzySearch(search, data.allMarkdownRemark.edges)
return (
<Layout>
<SearchResults FoundItems={results} SearchedTerm={search}> </SearchResults>
</Layout>
)
}
export const query = graphql `
query MyQuery {
allMarkdownRemark {
edges {
node {
fields {
slug
}
frontmatter {
title
date
doctype
}
html
}
}
}
}
`
SearchResults.js
import React from 'react'
import { Link } from 'gatsby'
import searchResultStyles from "./searchresults.module.css"
function resultsPage(resultsBlurb, results) {
return(
<div className={searchResultStyles.content}>
<h1>Search Results</h1>
<p className={searchResultStyles.resultBlurb}>{resultsBlurb}</p>
<ol>
{results.map((match) => (
<li>
<div className={searchResultStyles.resultContent}>
<Link to={match.slug} className={searchResultStyles.resultTitle}>{match.title}</Link>
{match.matches.map(function(instanceOfMatch) {
if(instanceOfMatch.key === "content") {
let startIndex = instanceOfMatch.indices[0][0]
return(
<p className={searchResultStyles.resultExcerpt}>{`...${instanceOfMatch.value.substring(startIndex, startIndex + 100)}...`}</p>
)
}
})}
</div>
</li>
))}
</ol>
</div>
)
}
class SearchResults extends React.Component {
constructor(props) {
super(props)
this.state = {
results: props.FoundItems,
term: props.SearchedTerm,
}
this.updateBlurb = this.updateBlurb.bind(this)
}
updateBlurb() {
let resultsBlurb = `Sorry--could not find any results for "${this.state.term}"`
if (this.state.results.length) {
resultsBlurb = (this.state.results.length === 1) ? `Only 1 item found for "${this.state.term}"` : `Found ${this.state.results.length} items for "${this.state.term}"`
}
return resultsBlurb
}
componentDidUpdate(prevProps) {
if(prevProps!== this.props) {
this.setState ({
results: this.props.FoundItems,
term: this.props.SearchedTerm
})
}
return(resultsPage(this.updateBlurb(), this.props.FoundItems))
}
render() {
return(resultsPage(this.updateBlurb(), this.state.results))
}
}
export default SearchResults
SOLUTION
(within search.js)
export default ({ location, data }) => {
var search = ''
var results = []
if(typeof window !== "undefiend") search = location.state.query.trim()
if(search.length) results = ...
location is short for window.location, but at build-time your code is running in Node.js which does not have a window. Instead consider testing for the existence of window (typeof window !== "undefined") before running your location.state.query.trim call, and fall back to a default value in the case that window does not exist.
I have created three react components and I don't know why I am getting an infinite network request and this warning: index.js:1375 Warning: Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state.
in MenuCategory (at App.js:19)
in App (at src/index.js:5)
also a network request in MenuItems.js is getting called in a loop. I think it is due to setState but I don't know where is the error.
And here is my code :
import React from "react";
import MenuCategory from "./components/MenuCategory";
import MenuItems from "./components/MenuItems";
class App extends React.Component {
constructor(props) {
super(props);
this.state = { shortName: "" };
}
handleProps = ss => {
if (this.state.shortName === "") {
this.setState({ shortName: ss });
}
// console.log(ss, ".../PP");
};
render() {
return (
<div className="App">
<MenuCategory callback={this.handleProps} />
<MenuItems shortNameProp={this.state.shortName} />
</div>
);
}
}
export default App;
import React from "react";
class MenuCategory extends React.Component {
constructor(props) {
super(props);
this.state = { category: "", selectedCat: "" };
}
async UNSAFE_componentWillMount() {
const url = "http://stream-restaurant-menu-svc.herokuapp.com/category";
await fetch(url)
.then(data => data.json())
.then(element => {
this.setState({ category: element });
});
}
menuCat = () => {
let cat = this.state.category;
// console.log(cat, "...Cat", this.state.selectedCat, "...Cat");
if (this.state.selectedCat !== "") {
this.props.callback(this.state.selectedCat);
}
return cat.map(items => {
return (
<li
key={items.short_name}
onClick={() => this.setState({ selectedCat: items.short_name })}
>
{items.name}
</li>
);
});
};
render() {
return <div>{this.state.category.length > 0 ? this.menuCat() : null}</div>;
}
}
export default MenuCategory;
import React from "react";
class MenuItems extends React.Component {
constructor(props) {
super(props);
this.state = { catItems: "", items: "" };
}
renderItems = () => {
let shortName = this.props.shortNameProp;
if (shortName !== "") {
const url =
"https://stream-restaurant-menu-svc.herokuapp.com/item?category=" +
shortName;
fetch(url)
.then(data => data.json())
.then(element => {
this.setState({ items: element });
});
}
if (this.state.items !== "") {
let selectedMenu = this.state.items;
console.log(selectedMenu);
return selectedMenu.map(item => {
return <div key={item.name}> {item.name}</div>;
});
}
};
render() {
return <div>{this.renderItems()}</div>;
}
}
export default MenuItems;
Let's call App a parent and MenuCategory a child.
Let's denote a function call as the '->' sign.
There is an infinite loop formed like that:
child.render -> child.menuCat -> child.props.callback -> parent.handleProps -> parent.setState -> parent.render -> child.render.
I am trying to map a dynamic array with an address and a string from solidity to react to look like a table or print out the address and string in a list but I can't manage to separate those 2 values.
class App extends Component {
constructor(props) {
super(props);
this.state = {
Data: []
};
}
GetData = async () => {
const { accounts, contract, count, Data } = this.state;
const data = [];
for (var i = 0; i < count.length; i++) {
const dataa = await contract.methods.getInfo(i).call();
data.push(dataa);
}
console.log(data);
this.setState({ Data: JSON.stringify(data) });
};
render() {
return (
<>
<button onClick={this.GetData}>Show</button>
<h1>{this.state.Data}</h1>
</>
);
}
}
export default App;
This is what my console prints and it shows the data in the website as 0:<address> 1: <string>
(2) [Result, Result]
0: Result
0: "0x7e3ce0fc8F95Bb83A4f5131912DacBFf11B9d4f8"
1: "{test1}"
__proto__: Object
1: Result {0: "0x514bdB4F417926027dDa4f0ccb2a6674a31D4BcB", 1: "{test2"}
length: 2
__proto__: Array(0)
Try separating before you stringify. Actually, why do you stringify at all?
This should do:
class App extends Component {
constructor(props) {
super(props);
this.state = {
Data: []
};
}
GetData = async () => {
const { accounts, contract, count, Data } = this.state;
const data = [];
for (var i = 0; i < count.length; i++) {
const dataa = await contract.methods.getInfo(i).call();
data.push(dataa);
}
console.log(data);
this.setState({ Data: data });
};
render() {
return (
<>
<button onClick={this.GetData}>Show</button>
{ this.state.Data.map(item => <h1>{item.toString()}</h1>) }
</>
);
}
}
export default App;
This question already has answers here:
Why is setState in reactjs Async instead of Sync?
(8 answers)
Closed 5 years ago.
I have an app like:
Main.js-
import React, { Component } from 'react';
import _ from 'underscore';
import { pick_attributes } from '../utils/general';
import ApplicationsButtons from '../components/ApplicationsButtons';
import Roles from '../components/Roles';
let applications_url = 'http://127.0.0.1:8889/api/applications'
export default class Main extends Component {
constructor(props) {
super(props);
this.state = {
applications: [],
selected_app_id: 1,
roles: []
};
this.updateSelectedApp = this.updateSelectedApp.bind(this);
this.updateApplicationData = this.updateApplicationData.bind(this);
this.loadAppData = this.loadAppData.bind(this);
this.getSelectedApplicationData = this.getSelectedApplicationData.bind(this);
this.setRoles = this.setRoles.bind(this);
}
componentDidMount() {
this.loadAppData();
}
// componentDidUpdate() {
// this.updateApplicationData();
// }
updateApplicationData() {
this.setRoles();
}
loadAppData() {
let self = this;
$.ajax({
url: applications_url,
method: 'GET',
success: function(data) {
let objects = data.objects;
self.setState({applications_data: objects});
let apps_data = pick_attributes(objects, 'name', 'id');
self.setState({applications: apps_data});
self.updateApplicationData();
}
});
}
getSelectedApplicationData() {
let selected_app_id = this.state.selected_app_id;
let objects = this.state.applications_data;
for (let i = 0; i < objects.length; i++) {
let object = objects[i];
if (object.id == selected_app_id) {
return object
}
}
}
setRoles() {
let selected_app_id = this.state.selected_app_id;
let selected_app_object = this.getSelectedApplicationData();
let roles_data = selected_app_object.role_list;
let roles = pick_attributes(roles_data, 'name', 'id');
this.setState({roles});
}
updateSelectedApp(id) {
this.setState({selected_app_id: id});
}
render() {
return (
<div>
{this.state.selected_app_id}
<ApplicationsButtons
apps={this.state.applications}
clickHandler={this.updateSelectedApp}/>
<Roles roles={this.state.roles} />
</div>
);
}
}
ApplicationsButtons.js-
import React, { Component } from 'react';
export default class ApplicationsButtons extends Component {
render() {
var buttons = null;
let apps = this.props.apps;
let clickHandler = this.props.clickHandler;
if (apps.length > 0) {
buttons = apps.map(function(app) {
return (
<button
onClick={() => clickHandler(app.id)}
key={app.id}>
{app.name} - {app.id}
</button>
);
});
}
return (
<div>
{buttons}
</div>
);
}
}
Roles.js-
import React, { Component } from 'react';
export default class Roles extends Component {
render() {
var roles_li_elements = null;
let roles = this.props.roles;
console.log(roles);
if (roles.length > 0) {
roles_li_elements = roles.map(function(role) {
console.log(role);
return (
<li key={role.id}>
{role.name}
</li>
);
});
}
return (
<div>
<h4>Roles:</h4>
<ul>
{roles_li_elements}
</ul>
</div>
);
}
}
I want the Roles to update when the user clicks a button that picks a new app. Right now, clicking the buttons does update state.selected_app_id, but I need setRoles() to be called each time selected_app_id changes. I tried throwing it in the onClick:
updateSelectedApp(id) {
this.setState({selected_app_id: id});
this.setRoles();
}
for some reason that only changed the roles after clicking each button twice.
componentDidUpdate() {
this.updateApplicationData();
}
causes state to update forever in an infinite loop. You aren't supposed to update state inside componentWillUpdate.
updateSelectedApp(id) {
this.setState({selected_app_id: id}, () => {
this.setRoles();
});
}