ReactJS Uncaught ReferenceError function is not defined - reactjs

I am trying to implement a custom validation in React using ES6 syntax.
import React, { Component } from 'react';
export default class Board extends Component {
constructor(props) {
super(props);
}
static propTypes = { count: validate };
validate(props, propName, componentName){
if (props[propName]) {
let value = props[propName];
if (typeof value === 'number') {
if (value > 100) {
return new Error("Value cannot be more than 100");
}
}
else{
return new Error('Count should be a number')
}
}
};
render() {
return (
<div className="board">{this.props.count}</div>
);
}
}
When I run this code, I get an error "Uncaught ReferenceError: validate is not defined". I will appreciate if someone could help me resolve this.

import React, { Component } from 'react';
export default class Board extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="board">{this.props.count}</div>
);
}
}
const validate = (props, propName, componentName) => {
if (props[propName]) {
let value = props[propName];
if (typeof value === 'number') {
if (value > 100) {
return new Error("Value cannot be more than 100");
}
}
else{
return new Error('Count should be a number')
}
}
};
Board.propTypes = {
count: validate
}
or more simple...
import React, { Component } from 'react';
export default class Board extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="board">{this.props.count}</div>
);
}
}
Board.propTypes = {
count: (props, propName, componentName) => {
if (props[propName]) {
let value = props[propName];
if (typeof value === 'number') {
if (value > 100) {
return new Error("Value cannot be more than 100");
}
}
else{
return new Error('Count should be a number')
}
}
}
}

You can’t access instance properties from static properties, so easiest solution would be to make validate static too.
static propTypes = { count: Board.validate }
static validate(props, propName, componentName) {
// ...
}
this.validate seems to work too but I don’t like the combination of static and using this.

Related

React with typescript ==>No overload matches this call

I am getting below error in the screeshot error_2
Here AgGridReact is imported from the ag-grid-react library which i have imported at the top of my code .So i want ask to how can I declare interface to the AgGridReact because it not the component .If it will be normal component then It will be easy to just declare the interface and declare the props inside it
Below is my code
import React, { Component } from 'react';
import { AgGridColumn, AgGridReact } from 'ag-grid-react';
import './Grid.scss';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
type MyProps = {
className:any
rowData:any
columns:any
updateRecord:any
onDeleteRecord:any
noHoverEffect:any
gridOptions:any
onRowEditingStopped:any
};
type MyState = {
};
export default class Grid extends Component<MyProps, MyState> {
constructor(props:MyProps) {
super(props);
this.state = {};
}
onCellClicked = (params:any) =>
{
// Handle click event for action cells
if (params.column.colId === "Action" && params.event.target.dataset.action)
{
let action = params.event.target.dataset.action;
if (action === "update")
{
this.props.updateRecord(params.node.data.id, params.node.data.name, params.node.data.description, params.node.data.created, params.node.data.created_By);
}
if (action === "delete") {
this.props.onDeleteRecord(params.node.data)
}
}
}
render() {
const gridOptions = {
getRowStyle: (params:any) => {
if (params.node.rowIndex % 2 === 1) {
return { background: '#ebebeb73' };
}
},
};
return (
<div className={["sct-grid", this.props.className, this.props.noHoverEffect && "nohover"].filter(Boolean).join(" ")}>
<AgGridReact gridOptions={gridOptions}
alignedGrid="true"
suppressDragLeaveHidesColumns={true}
pagination={true}
paginationPageSize={7}
rowData={this.getitems()}
onRowEditingStopped={this.onRowEditingStopped}
onRowEditingStarted={this.onRowEditingStarted}
onCellClicked={this.onCellClicked}
editType="fullRow"
suppressClickEdit={true}
enableRangeSelection={true}
columnDefs={this.props.columns}
>
{/* { this.getColumns()}*/}
</AgGridReact>
</div>
);
}
getitems() {
return this.props.rowData;
}
getColumns() {
var listOfColumns :any = [];
if (this.props.columns) {
this.props.columns.forEach((column:any) => {
listOfColumns.push(<AgGridColumn key={column} minWidth="80" maxWidth="120" field={column.field} sortable={column.sortable} filter={column.filter}></AgGridColumn>);
});
}
return listOfColumns;
};
};
Following the documentation, you either need to add getRowStyle property to the AgGridReact component, and/or always return styles from getRowStyle function in gridOptions. Because right now, if your condition if (params.node.rowIndex % 2 === 1) returns false, getRowStyle function is going to return undefined(which AgGridReact apparently doesn't like if looking at the error message).

ReactJS -- Unable to find latest title from an api causing error

I have a Landing component and a NewsLatest component. I am hitting on an api and trying to find the article with the latest timestamp but iam unable to get it done in reactJS.I checked the js code its working fine but in react it is not rendering. Kindly suggest something.
import React, { Component } from 'react'
import NewsSearch from '../NewsSearch/NewsSearch';
import NewsLatest from '../NewsLatest/NewsLatest';
import './Landing.css';
import axios from 'axios';
class Landing extends Component {
state={
newsList: []
}
componentDidMount(){
axios.get(`https://api.nytimes.com/svc/topstories/v2/home.json?api-key=7cK9FpOnC3zgoboP2CPGR3FcznEaYCJv`)
.then(res=> {
this.setState({newsList: res.data.results});
});
}
render() {
// console.log(this.state.newsList);
return (
<div className="landing text-center text-white">
<h1>News Portal</h1>
<div className="news-search">
<NewsSearch />
</div>
<div className="news-latest">
<NewsLatest newsList={this.state.newsList}/>
</div>
</div>
)
}
}
export default Landing;
import React, { Component } from 'react';
// import PropTypes from 'prop-types';
class NewsLatest extends Component {
constructor(props){
super(props);
this.state = {
newsTitle:'',
abstract:'',
newsUrl:'',
}
// this.newsLatest = this.newsLatest.bind(this);
}
newsLatest = (e)=>{
// e.preventDefault();
const {newsList} = this.props;
let maxTime = newsList.map(function(o) {
return new Date(o.updated_date);
});
let maximumValue = Math.max(...maxTime);
let latestnews = newsList.filter(function (el) {
return maximumValue === new Date(el.updated_date).getTime();
})[0];
if(latestnews){
this.setState({newsTitle: latestnews.title});
return (<h4>{this.state.newsTitle}</h4>);
}
}
newsTitle = () => (
this.props.newsList.map(item => (<h2 key={item.title}>{item.title}</h2>))
)
render() {
console.log(this.props.newsList);
return (
<div>
<h2>News Latest....</h2>
{this.newsLatest()}
</div>
);
}
}
export default NewsLatest;
There is some issue in rendering in NewsLatest component. KIndly suggest something.
Try this:
You must probably be getting a maximum depth error, use a lifecycle method instead like componentDidUpdate. Update your component state only if the previous props are different from the newer ones.
Read more here: https://reactjs.org/docs/react-component.html
import React, { Component } from "react";
// import PropTypes from 'prop-types';
class NewsLatest extends Component {
constructor(props) {
super(props);
this.state = {
newsTitle: "",
abstract: "",
newsUrl: ""
};
// this.newsLatest = this.newsLatest.bind(this);
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.newsList !== this.props.newsList) {
const { newsList } = this.props;
let maxTime = newsList.map(function(o) {
return new Date(o.updated_date);
});
let maximumValue = Math.max(...maxTime);
let latestnews = newsList.filter(function(el) {
return maximumValue === new Date(el.updated_date).getTime();
})[0];
this.setState({ newsTitle: latestnews.title });
}
}
// newsLatest = e => {
// // e.preventDefault();
// const { newsList } = this.props;
// let maxTime = newsList.map(function(o) {
// return new Date(o.updated_date);
// });
// let maximumValue = Math.max(...maxTime);
// let latestnews = newsList.filter(function(el) {
// return maximumValue === new Date(el.updated_date).getTime();
// })[0];
// console.log(latestnews)
// if (latestnews && latestnews.hasOwnProperty('length') && latestnews.length>0) {
// return <h4>{this.state.newsTitle}</h4>;
// }
// };
newsTitle = () =>
this.props.newsList.map(item => <h2 key={item.title}>{item.title}</h2>);
render() {
console.log(this.props.newsList);
return (
<div>
<h2>News Latest....</h2>
<h4>{this.state.newsTitle}</h4>
</div>
);
}
}
export default NewsLatest;
Also, a sandbox: https://codesandbox.io/s/hungry-frog-z37y0?fontsize=14

reset On Resolve the course to loop in React

I'm trying to reset the Values on change of the Dependency value to the SelectInput. But it course to loop and break the page. Here find the code I have done so far.
How can omit this on my code.
import {
SelectInput,
required
} from 'react-admin';
import data from '../data';
import { withStyles } from '#material-ui/core/styles';
import React, { Component } from 'react';
import { DependentInput } from 'aor-dependent-input';
const initialState = {
way_of_join: data.way_of_join
};
class WayOfJoinSelectInput extends Component {
constructor(props) {
super(props)
this.state = initialState;
}
reset(){
this.setState({initialState});
}
switchSector = (props) => {
if (props !== undefined && Object.keys(props).length > 0) {
var value = props.General_Service.service_sector;
this.reset();
switch (value) {
case 'sleas':
this.state.way_of_join.splice(4, 3)
break;
case 'sltes':
this.state.way_of_join.splice(2, 1)
break;
}
}
};
render() {
return (
<DependentInput resolve={this.switchSector}>
<SelectInput
source="General_Service.way_join"
label="Way of Join"
validate={required()}
// onChange={this.reset()}
choices={this.state.way_of_join}
/>
</DependentInput>
)
}
}
export default withStyles(styles)(WayOfJoinSelectInput);
Here find what getting on error.
import {
SelectInput,
required
} from 'react-admin';
import data from '../data';
import { withStyles } from '#material-ui/core/styles';
import React, { Component } from 'react';
import { DependentInput } from 'aor-dependent-input';
const initialState = {
way_of_join: data.way_of_join
};
class WayOfJoinSelectInput extends Component {
constructor(props) {
super(props)
this.state = initialState;
this.reset=this.reset.bind(this);
}
reset(){
this.setState({initialState});
}
switchSector = (props) => {
if (props !== undefined && Object.keys(props).length > 0) {
var value = props.General_Service.service_sector;
this.reset();
switch (value) {
case 'sleas':
this.state.way_of_join.splice(4, 3)
break;
case 'sltes':
this.state.way_of_join.splice(2, 1)
break;
}
}
};
render() {
return (
<DependentInput resolve={this.switchSector}>
<SelectInput
source="General_Service.way_join"
label="Way of Join"
validate={required()}
onChange={this.reset}
choices={this.state.way_of_join}
/>
</DependentInput>
)
}
}
export default withStyles(styles)(WayOfJoinSelectInput);
You need to bind the functions in constructor or use arrow functions.

Dynamically generating React elements not assignind properties

I want to use my ViewModel Component to dynamically create elements and assign properties to them. The code I have is rendering, but not what I expect. It's rendering the text in a div instead of creating my custom Debug element.
Here is Debug:
import React, { Component } from 'react';
class Debug extends Component {
render() {
return (<h3>
{this.props.o}
</h3>)
}
}
export default Debug;
I want props.o to be a shorthand for object assigned to an element, assigned in ViewModel:
Here is my ViewModel:
import React, { Component } from 'react';
class ViewModel extends Component {
loadData() {
this.setState({});
}
componentWillMount() {
this.loadData();
if (!this.state) { return; }
let stateKeys = Object.keys(this.state);
console.log(stateKeys);
if (stateKeys.length <= 0) { return; }
let elems = {};
console.log("My statekeys" + stateKeys);
for (let key of stateKeys) {
let stateValue = this.state[key];
console.log("My state value: " + stateValue);
let tagName = stateValue[0];
let values = stateValue[1];
elems[key] = values.map((item, i) => {
return React.createElement(tagName, {o: item, key: key + "" + i});
});
}
}
render() {
let keys = Object.keys(this.state);
let output = [];
for (let k of keys) {
let group = this.state[k];
for (let elem of group) {
output.push(elem);
}
}
return (<div>{output}</div>)
}
}
And using with:
class Fight extends ViewModel {
loadData() {
console.log("Loading data with recent");
this.setState({
recent: [Debug, ["Lightning Blast for 155, Critical!", "Enemy Fire Punches for 70."]]
});
}
export default ViewModel;
HTML output:
<div><div>Lightning Blast for 155, Critical!Enemy Fire Punches for 70.</div></div>
No h3. The CreateElement seems to be putting the text into the body when I want it to go into the props.
Here is the working code for dynamically generating tags in React:
import React, { Component } from 'react';
class Debug extends Component {
render() {
return (<h3>
Hey{this.props['o']}
</h3>)
}
}
export default Debug;
class Fight extends ViewModel {
loadData() {
console.log("Loading data with recent");
let myState = {
"recent": [Debug, ["LBlast", "FPunch."]]
};
this.setState(myState);
}
ViewModel
import React, { Component } from 'react';
class ViewModel extends Component {
loadData() {
this.setState({});
}
componentWillMount() {
this.loadData();
}
render() {
if (!this.state) {
return (<div></div>)
}
if (!this.state) { return; }
let stateKeys = Object.keys(this.state);
console.log(stateKeys);
if (stateKeys.length <= 0) { return; }
let elems = {};
console.log("My statekeys" + stateKeys);
for (let key of stateKeys) {
let stateValue = this.state[key];
console.log("My state value: " + stateValue);
const TagName = stateValue[0];
console.log("What is tagname?" + TagName);
let values = stateValue[1];
elems[key] = values.map((item, i) => {
console.log("My item is" + item);
return <TagName o={item} key={key + "" + i}/>;
});
}
let keys = Object.keys(elems);
let output = [];
for (let k of keys) {
let group = elems[k];
for (let elem of group) {
output.push(elem);
}
}
console.log(output);
return <div>{output}</div>
}
}
export default ViewModel;

Is it possible to set the context after the component mounts in React?

I wish to add the checks done (once the component mounts in CDM) to detect userAgent - for the purposes of mobile/flash/touchDevice detections to context rather than to the state. Is this possible? if so how would you do that? I am currently getting undefined when I attempt to access the value fo the context for the isFlashInstalled. Here is glimpse into the component setting the context:
App.js
export class App extends Component {
static childContextTypes = {
isFlashInstalled: React.PropTypes.bool
};
constructor() {
super();
this.state = {
isFlashInstalled: false
};
}
getChildContext() {
return {
isFlashInstalled: this.state.isFlashInstalled
};
}
componentDidMount() {
const flashVersion = require('../../../client/utils/detectFlash')();
// I know this could be done cleaner, focusing on how for now.
if (flashVersion && flashVersion.major !== 0) {
this.setFlashInstalled(true);
} else {
this.setFlashInstalled(false);
}
}
setFlashInstalled(status) {
this.setState({isFlashInstalled: status});
}
}
Later when trying to access isFlashInstalled from context I will get undefined
ChildComponent.js
export class ChildComponent extends Component {
// all the good stuff before render
render() {
const {isFlashInstalled} = this.context
console.log(isFlashInstalled); // undefined
}
}
did you correctly set up context types for parent and child? I did a test and it works, see the componentDidMount that set the state asynchronously:
class Parent extends React.Component {
state = {
color: 'red'
}
getChildContext() {
return {
color: this.state.color
};
}
componentDidMount() {
setTimeout(() => this.setState({color: 'blue'}), 2000)
}
render() {
return (
<div>Test <Button>Click</Button></div>
);
}
}
Parent.childContextTypes = {
color: React.PropTypes.string
}
class Button extends React.Component {
render() {
return (
<button style={{background: this.context.color}}>
{this.props.children}
</button>
);
}
}
Button.contextTypes = {
color: React.PropTypes.string
};
http://jsbin.com/cogikibifu/1/edit?js,output

Resources