where is the "this.props" defined? - reactjs

Any help or hint would be greatly appreciated.
In SearchBar.js, where is the "this.props" defined?
I don't see this variable being defined in the SearchBar.js class?
Is it because of React.Component class?
How can I go into this React.Component class when debugging in google chrome?
SearchBar.js:
import React from 'react';
class SearchBar extends React.Component {
state = { term: '' };
onFormSubmit = event => {
event.preventDefault();
this.props.onSubmit(this.state.term);
console.log(this.state.term);
}
render() {
return (
<div className="ui segment">
<form onSubmit={this.onFormSubmit} className="ui form">
<div className="field">
<label>Image Search</label>
<input type="text" value={this.state.term} onChange={(e) => this.setState({ term: e.target.value.toUpperCase()})} />
</div>
</form>
</div>);
}
}
App.js:
import React from 'react';
import SearchBar from './SearchBar';
class App extends React.Component {
onSearchSubmit(term) {
console.log(term);
}
render() {
return (
<div className="ui container" style={{ marginTop: '10px'}}>
<SearchBar onSubmit={this.onSearchSubmit} />
</div>
);
}
}
export default App;
export default SearchBar;

The superclass, React.Component, creates a props object on the instance and assigns to it any props passed to the instance. If you go to react.development.js (or to ReactBaseClasses.js), you'll see:
function Component(props, context, updater) {
this.props = props;
where the first argument, the props, will contain props the component was called with.
Here, since the component is invoked like this:
<SearchBar onSubmit={this.onSearchSubmit} />
It has one prop, onSubmit, so the props are:
{
onSubmit: this.onSearchSubmit
}

Related

Uncaught TypeError: Cannot read properties of undefined (reading 'toLowerCase') React - Redux

i'm getting the following error while trying to search. I'm using redux to hold my state. Everytime i navigate away from the following page and back to it i get the error.
"Uncaught TypeError: Cannot read properties of undefined (reading 'toLowerCase')"
the following is my insurance component
import React, { Component } from 'react';
import { connect } from "react-redux";
import { fetchAllInsurances } from '../../actions/insurance.action';
import { Link } from 'react-router-dom';
import Card from '../Card';
import SearchBar from '../SearchBar';
import Header from '../Header';
export class Insurance extends Component {
constructor(props){
super(props);
this.state = {sCode:null};
}
onSearchSubmit = (term) => {
this.setState({sCode:term})
}
componentDidMount(){
this.props.fetchAllInsurances();
}
render() {
return (
<>
<Header/>
<div>
<SearchBar onSubmit={this.onSearchSubmit}/>
</div>
<br></br>
{this.renderCreate()}
<br></br>
<br></br>
<br></br>
{this.renderCard()}
</>
)
}
renderCreate(){
return(
<>
<Link to ={'/addinsurance'} className = "ui primary button">Add Insurance</Link>
</>
)
}
renderCard(){
return(
<div className="ui four column grid">
{this.props.insurance.filter(((c)=>{
if(this.state.sCode == null){
return c;
}
else if(c.VendorName.toLowerCase().includes(this.state.sCode.toLowerCase().toString())){
return c
}
})).map((c, i) => (
<Card key={i} InsData={c} />
))}
</div>
)
}
}
const mapStateToProps = state =>{
return{
insurance:Object.values(state.insurance)
}
}
export default connect(mapStateToProps,{fetchAllInsurances})(Insurance);
the following is my search component
import React from 'react'
class SearchBar extends React.Component {
state = {term:''};
onFormSubmit =(event) =>{
event.preventDefault();
//send the state data to the parent
this.props.onSubmit(this.state.term);
}
render(){
return (
<div className='ui segment'>
<form onSubmit = {this.onFormSubmit} action="" className="ui form">
<div className="field">
<label>Insurance Vendor Search</label>
<div className="searchInputs">
<input
type="text"
value={this.state.term}
onChange={e=> this.setState({term:e.target.value})}
placeholder='Enter the insurance vendor to search...'/>
</div>
</div>
</form>
</div>
)
}
}
export default SearchBar;
As the error state, the variable is undefined. You will need to test the variable first.
So either use
c.VendorName?.toLowerCase()
or
if (c.VendorName) {
c.VendorName.toLowerCase()........
}

I am getting no-undef when I am trying to run my react app

When I am trying to run my react app it shows me the following error.
Earlier The code was working on a different app. But when I created a new app and trying to create any function or state it is showing it is undefined
The Code is provided below -
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App'
ReactDOM.render(<App />, document.getElementById('root'));
App.js
import React from 'react';
import SearchBar from './SearchBar';
class App extends React.Component {
onSearchSubmit = (term) => {
console.log(term)
};
render() {
return (
<div className="ui container" style={{ marginTop: '10px' }}>
<SearchBar onSubmit={this.onSearchSubmit} />
</div>
);
}
}
export default App;
SearchBar.js is
import React from 'react';
class SearchBar extends React.Component {
state = { term: '' };
onFormSubmit = (event) => {
event.preventDefault();
this.props.onSubmit(this.state.term);
}
render() {
return (
<div className="ui segment">
<form onSubmit={this.onFormSubmit} className="ui form">
<div className="field">
<label>Image Search</label>
<input
type="text"
onChange={e => this.setState({ term: e.target.value })}
value={this.state.term}
/>
</div>
</form>
</div>);
}
}
export default SearchBar;
The error shown is -
Failed to compile
src/components/App.js
Line 7:9: 'onSearchSubmit' is not defined no-undef
src/components/SearchBar.js
Line 4:5: 'state' is not defined no-undef
Line 6:5: 'onFormSubmit' is not defined no-undef
Search for the keywords to learn more about each error.
I think you're missing a constructor in your components
class SearchBar extends React.Component {
constructor(props) {
super(props);
this.state = {
term: ''
};
}
//...
}

Change image in component based on dropdown value in another component using React

I am new to React. I have three components: a top-level App.js component which renders a ProductOptions.js component and a ProductImage.js component. I'd like to change the image displayed in the ProductImage component based on the value of the dropdown in the ProductOptions component. When App renders the first time, the default selection is Black and the corresponding product-black.jpg image will show in the ProductImage component. The user can switch to Brown which should show the product-brown.jpg image in the ProductImage component.
I know I need to update state and use an onChange event to listen for the value of the dropdown but I'm unsure of how to wire it all together.
App component:
import React from 'react';
import ProductOptions from './ProductOptions';
import ProductImage from './ProductImage';
class App extends React.Component {
render() {
return (
<div className="container">
<div className="row">
<div className="col-8">
<ProductOptions />
</div>
<div className="col-4">
<ProductImage />
</div>
</div>
</div>
);
}
}
export default App;
ProductOptions component:
import React from 'react';
class ProductOptions extends React.Component {
render() {
return (
<div id="product-options">
<form>
<label for="colors">Colors</label>
<select className="form-control form-control-sm" id="colors" name="colors">
<option value="Black">Black</option>
<option value="Brown">Brown</option>
</select>
</form>
</div>
);
}
}
export default ProductOptions;
ProductImage component:
import React from 'react';
import productBlack from '../images/product-black.jpg';
import productBrown from '../images/product-brown.jpg';
class ProductImage extends React.Component {
render() {
return (
<div id="product-image">
<img
alt="tempalt"
className="img-fluid"
src={tempsource}
/>
</div>
);
}
}
export default ProductImage;
Your main App has two child components ProductOptions & ProductImage, who are also siblings, which need to communicate with each other.
App qualifies to own the state, which stores the current product to be displayed to the user, in the variable selectedProduct.
selectedProduct is passed down as props (named likewise) to both the components
this.handleSelectedProduct() is passed to ProductOptions to be invoken onChange and the App state is set with the selected product
A ternary operator is used, which checks the string passed to accordingly render the image.
App component:
import React from "react";
import ProductOptions from "./ProductOptions";
import ProductImage from "./ProductImage";
class App extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
selectedProduct: "Black"
};
}
handleSelectedProduct = selection => {
this.setState({ selectedProduct: selection });
};
render() {
return (
<div className="container">
<div className="row">
<div className="col-8">
<ProductOptions
handleSelectedProduct={this.handleSelectedProduct}
selectedProduct={this.state.selectedProduct}
/>
</div>
<div className="col-4">
<ProductImage selectedProduct={this.state.selectedProduct} />
</div>
</div>
</div>
);
}
}
export default App;
ProductOptions component:
import React from "react";
class ProductOptions extends React.Component {
render() {
return (
<div id="product-options">
<form>
<label for="colors">Colors</label>
<select
className="form-control form-control-sm"
id="colors"
name="colors"
value={this.props.selectedProduct}
onChange={e => {
this.props.handleSelectedProduct(e.target.value);
}}
>
<option value="Black">Black</option>
<option value="Brown">Brown</option>
</select>
</form>
</div>
);
}
}
export default ProductOptions;
ProductImage component:
import React from "react";
import productBlack from "../images/product-black.jpg";
import productBrown from "../images/product-brown.jpg";
class ProductImage extends React.Component {
render() {
const { selectedProduct } = this.props;
return (
<div id="product-image">
<img
alt="tempalt"
className="img-fluid"
src={selectedProduct === "Black" ? productBlack : productBrown}
/>
</div>
);
}
}
export default ProductImage;

How can get Value from child component in react?

I create a InputComponent and I want to import this component in other component and do submit, but I can't do it. how can I get value from child component in my FormComponent
InputComponent.js
import React, {Component} from 'react';
class InputComponent extends Component {
constructor(props) {
super(props);
this.state = { currentVal: null }
}
render() {
return (
<div>
<input
value={this.state.currentVal}
onChange={(event) => this.setState({currentVal:event.target.value })}
/>
</div>
);
}
}
export default InputComponent;
FormComponent.js
import React,{Component} from 'react';
import InputComponent from '../../components/common/InputComponent';
class FormComponent extends Component {
constructor(props) {
super(props);
this.state = { }
}
CallSubmit= (event) => {
// how can get username and password ?
event.preventDefault();
console.log(event.target.vale)
}
render() {
return (
<div style={{width:100, height:500, marginTop:100}}>
<form onSubmit={ this.CallSubmit }>
<InputComponent name="username" />
<InputComponent name="password" />
<button>Send it</button>
</form>
</div>
);
}
}
export default FormComponent;
You can create an onChange action on child component, for example here is your FormComponent:
Create this function to handle change:
onChangeUsername(username){
this.setState({username})
}
Passing the props to child component:
<InputComponent name="username" onChange = {this.onChangeUsername} />
And in the child component(InputComponent), you can access this props and pass the data to it:
this.props.onChange(event.target.value)
move your onChange functions in parent component and store username and password in FormComponent component
In React, data flows one way, from parent to children.
Therefore, you need to have the input' actual states at the FormComponent and pass them as props to the InputComponent, and the function that deals with it at the FormComponent either.
<div>
<InputComponent
input={this.state.username}
onChange={this.handleInputChange}
/>
<InputComponent
input={this.state.password}
onChange={this.handleInputChange}
/>
</div>
A good article to understand it: https://openclassrooms.com/en/courses/4286486-build-web-apps-with-reactjs/4286721-understand-one-way-data-bindings

Passing state in React from two different components

I have a TopNab bar (component), which contains a SearchBar component. My Main component is rendering out TopNav, the main container component (Profile), and the Footer component. I want my SearchBar component to pass its state to the main container component so that the Profile component can use it.
What I am trying to build:
A user types a name into search bar and submits.
The profile matching the user name is displayed in the main container component.
Right now I have a component that can render out user profiles. I also have a component thats state updates to the user submitted value. What I need to do is pass this user submitted value to my profile component in order to render out the correct profile.
Is this possible or do I need to rebuild my components so the search is included in the Profile component?
SearchBar
import React, { Component, PropTypes } from 'react';
import Profile from './Profile';
class SearchBar extends Component {
constructor(props){
super(props)
this.state = {
name: ''
}
}
handleChange(e) {
this.setState({
name: e.target.value
});
}
handleSubmit(e) {
e.preventDefault();
console.log("searching for NAME " + this.state.name);
let profileName = this.state.name;
//PASS STATE TO PROFILE COMPONENT
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit.bind(this)}>
ARMORY BETA
<input type="text" placeholder="Enter Name"
name="name"
value={this.state.name}
onChange={this.handleChange.bind(this)} />
<button className="btn btn-success" type="submit">Search</button>
</form>
</div>
)
}
}
export default SearchBar;
Profile
import React, { Component, PropTypes } from 'react';
import SearchBar from './SearchBar';
import ProfileContainer from '../containers/ProfileContainer';
class Profile extends Component {
render() {
return (
<div className="cols2">
<div>[IMG]</div>
<div>
<ProfileContainer name={this.props.name}/>
</div>
</div>
)
}
}
Profile.PropTypes = {
name: PropTypes.string
}
Profile.defaultProps = {
name: ''
}
export default Profile;
Main
import React, { Component } from 'react';
import TopNav from './TopNav';
import Footer from './Footer';
import Profile from './Profile';
class Main extends Component {
render() {
return (
<div className="container-fluid">
<div className="row">
//TopNav calls SearchBar
<TopNav />
</div>
<div className="row">
<Profile />
</div>
<div className="row">
<Footer />
</div>
</div>
)
}
}
export default Main;
In Main, you should add a prop to <TopNav /> that points to a handler method that will propagate the profileName state change back to Main. This, in turn, will cause Profile to be re-rendered. The handler method takes one argument profileName and is called from the handleSubmit method in TopNav. Here's the code:
SearchBar
class SearchBar extends Component {
. . .
handleSubmit(e) {
e.preventDefault();
console.log("searching for NAME " + this.state.name);
let profileName = this.state.name;
this.props.handleProfileChange(profileName);
}
. . .
}
SearchBar.propTypes = {
handleProfileChange: React.PropTypes.func.isRequired,
}
Main
class Main extends Component {
constructor(props) {
super(props);
this.state = { profileName: '' }
handleProfileChange = this.handleProfileChange.bind(this);
}
handleProfileChange(profileName) {
// This state change will force Profile component to be re-rendered
this.setState( { profileName });
}
render() {
return (
<div className="container-fluid">
<div className="row">
//TopNav calls SearchBar
<TopNav handleProfileChange={this.handleProfileChange} />
</div>
<div className="row">
<Profile profileName={this.state.profileName} />
</div>
<div className="row">
<Footer />
</div>
</div>
)
}
You'll need to expose a property on SearchBar that accepts a callback that will be called to indicate to its parent that the form was submitted (e.g. onSubmit)...
handleSubmit(e) {
e.preventDefault();
console.log("searching for NAME " + this.state.name);
let profileName = this.state.name;
//PASS STATE TO PROFILE COMPONENT
this.props.onSubmit(yourFormData);
}
...TopNav won't handle onSubmit itself, but just pass it on up to its own parent (perhaps renaming to "onSearchBarSubmit" along the way to make the name clearer from the perspective of TopNav's parent):
class TopNav extends Component {
render() {
return (
<div className="container-fluid">
<SearchBar onSubmit={this.props.onSearchBarSubmit}
</div>
);
}
}
class Main extends Component {
render() {
return (
<div className="container-fluid">
<div className="row">
<TopNav onSearchBarSubmit={ (criteria) => this.searchForStuff(criteria) } />
</div>
<div className="row">
<Profile data={this.state.stuffYouGotBackFromSearch} />
</div>
<div className="row">
<Footer />
</div>
</div>
)
}
}
...OR, in some cases, it can be desirable to un-nest the components, allowing SearchBar as one of TopNav's props.children. This allows you to handle onSubmit directly within Main, and pass anything it receives onto Profile:
class Main extends Component {
render() {
return (
<div className="container-fluid">
<div className="row">
//TopNav calls SearchBar
<TopNav>
<SearchBar onSubmit={ (criteria) => this.searchForStuff(criteria) } />
</TopNav>
</div>
<div className="row">
<Profile data={this.state.stuffYouGotBackFromSearch} />
</div>
<div className="row">
<Footer />
</div>
</div>
)
}
}
...a side-benefit of un-nesting is that it would allow you to use TopNav and Searchbar independently.

Resources