I start learning React, but i have some difficulty to figure out this error.
I have a parent component Weather and a child component WeatherForm. From the parent component i set a property for the child component. The child component is a form, and the goal is to get the text from an input and when the user clicks the submit button, the input text is passed to a function of the parent component which displays an alert with the text.
This is the parent component:
const WeatherForm = require('WeatherForm');
const WeatherMessage = require('WeatherMessage');
class Weather extends Component {
constructor(props) {
super(props);
this.state = {
location: ''
};
this.handleSearch = this.handleSearch.bind(this);
}
render() {
return (
<div>
<h3>Weather component</h3>
<WeatherForm onSearch={this.handleSearch} />
<WeatherMessage />
</div >
);
}
handleSearch(value) {
alert(value);
}
}
And this is the child component:
class WeatherForm extends Component {
constructor(props) {
super(props);
this.onFormSubmit = this.onFormSubmit.bind(this);
}
render() {
return (
<div>
<form onSubmit={this.onFormSubmit}>
<input type="text" placeholder="Enter a city name" ref="location" onChange={this.onFormSubmit}/>
<button>Get weather</button>
</form>
</div>
);
}
onFormSubmit(e) {
e.preventDefault();
let location = this.refs.location;
if (location.value && location.value.length > 0) {
this.refs.location.value = '';
props.onSearch(location.value);
}
}
}
But when i click the submit button, i am getting this error:
props.onSearch is not a function
Where I am making mistake?
I am also using the the parent component Weather in a Route in another component like this <Route exact path="/" component={Weather} />
Thanks to all
you are missing the this context for your function call.
change props.onSearch to this.props.onSearch
reflected in your handler
onFormSubmit(e) {
e.preventDefault();
const value = this.refs.location.value;
if (value && value.length > 0) {
this.refs.location.value = '';
this.props.onSearch(value);
}
}
Related
I have a FileUploader which needs to trigger from outside the component via prop, i have been battling for hours and could not figure out.
export class App {
let button = (<button>Click me please!</button>);
render() {
return (
<div className="app">
{button}
<FileUploader trigger={button} />
</div>
);
}
}
export class FileUploader {
constructor(props) {
this.trigger = props.trigger; // <button>Click me please!</button>
// do something to attach an onclick trigger element to simulate a
// click to the file input
}
render() {
return (
<div className="file-uploader">
<input type="file" style="display: none;">
<div>
// display the file image and some other additional file info
</div>
</div>
);
}
}
i wish that this.trigger will simulate a click to the input, which will open up a window to select files .. how can i do this? much appreciated
You can pass a empty ref to FileUploader from the parent component, and we will assign that ref to the input-file, and when you click on the button you have the access to the input, so you can manually trigger click
export default class App extends React.Component {
constructor(props) {
super(props);
this.fileInput = React.createRef(); // Create a empty ref
}
openFileInput = () => {
this.fileInput.current.click();
// since we have access to the fileinput, we can trigger manual click
};
render() {
return (
<div>
<button type="button" onClick={this.openFileInput}>
open file browser in child component
</button>
.......
<FileInput fileInputRef={this.fileInput} />
// pass the empty ref to the file input so we can assign it to the input-file
</div>
);
}
}
export class FileInput extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="file-uploader">
....
<input
type="file"
ref={this.props.fileInputRef} // assign the ref to the input
style={{ display: "none" }}
/>
</div>
);
}
}
DEMO
Here is a small example of how you can pass function to child component from parent and call them from child component.
import React from "react";
import ReactDOM from "react-dom";
class Children extends React.Component {
constructor(props) {
super(props);
this.onPress = props.onPress;
}
render = () => {
return (
<div>
<button onClick={this.onPress} color="success">
Child Click
</button>
</div>
);
};
}
class Parent extends React.Component {
fromParent = () => {
alert("Called from children");
};
render() {
return <Children onPress={this.fromParent} />;
}
}
ReactDOM.render(<Parent />, document.getElementById("root"));
I'm trying to pass input value from one child to another child using setState. It renders the first element, but not the second element in the first child...
class App extends Component {
constructor(props) {
super(props);
this.state = {};
};
showTekst = () => {
const inpValue = document.querySelector('.inpValue').value;
this.setState({
name: 'Bruce Wayne',
namefromvalue: inpValue.value
});
}
render() {
return (
<div className="app">
<Button showTekst={this.showTekst.bind(this)} />
<Text name={this.state.name} namefromvalue={this.state.namefromvalue}/>
<Inputvalue />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
class Inputvalue extends Component {
render() {
return (
<input className="inpValue"></input>
);
}
}
class Text extends Component {
render() {
return (
<div>
<h1>This is text..</h1>
<h2>{this.props.namefromvalue}</h2>
<p>{this.props.name}</p>
</div>
);
}
}
If you want to show the text from the Inputvalue component in the Text component only when the Button component is clicked you can store the input value in the App instance and update the App state when the Button is clicked.
To do so, we define an onChange prop in the Inputvalue component so that every time the text in the input changes, the prop is called with the new value. With that prop we update the value in the App instance. This value will always be in sync with the input value.
Last, when the button is clicked we update the App state with the input value so that the Text component renders its value.
class App extends Component {
constructor(props) {
super(props);
this.state = {};
// This variable will hold the input value.
this.inputValue = "";
}
showTekst = () => {
// Update with the current input value.
this.setState({
name: "Bruce Wayne",
namefromvalue: this.inputValue
});
};
onInputChange = value => {
// Update the input value.
this.inputValue = value;
};
render() {
return (
<div className="app">
<Button showTekst={this.showTekst.bind(this)} />
<Text name={this.state.name} namefromvalue={this.state.namefromvalue} />
<Inputvalue onChange={this.onInputChange} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
class Button extends Component {
render() {
return <button onClick={this.props.showTekst}>Show text</button>;
}
}
class Inputvalue extends Component {
render() {
return (
<input
className="inpValue"
onChange={ev => this.props.onChange(ev.target.value)}
/>
);
}
}
class Text extends Component {
render() {
return (
<div>
<h1>This is text..</h1>
<h2>{this.props.namefromvalue}</h2>
<p>{this.props.name}</p>
</div>
);
}
}
So I have a component "itemSelection" and inside of it I map through an api response like this
<div className="row">
{this.state.items.map(i => <Item name={i.name} quantity={i.quantity} />)}
</div>
Here the state of "Item" component
constructor(props){
super(props);
this.state = {
visible: false,
selected: false,
}
}
How could I pass the state of "Item" component to "itemSelection" component?
Sending data back up to your parent component should be done by using props.
Fairly common question, see this post for the long answer.
As according to me, If I understood your question you want to call the state of the child component to the parent component.
//Child.js
import s from './Child.css';
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
export default withStyles(s)(Child);
//Parent.js
class Parent extends Component {
render() {
onClick() {
this.refs.child.getAlert()
}
return (
<div>
<Child ref="child" />
<button onClick={this.onClick.bind(this)}>Click</button>
</div>
);
}
}
Also, you can get the code reference from the link: https://github.com/kriasoft/react-starter-kit/issues/909
This a little tricky but Maybe, its help you solving your problem.
//Parent.js
class Parent extends Component {
component(props) {
super(props)
this.state = {
test: 'abc'
}
}
ParentFunction = (value) => {
this.state.test = value;
this.setState(this.state);
}
render() {
return (
<div>
<Child
test={this.state.test}
ParentFunction={this.ParentFunction}
/>
</div>
);
}
}
//Child.js
import s from './Child.css';
class Child extends Component {
component(props) {
super(props)
this.state = {
test: props.test
}
}
handleChange = () => {
this.state.test = event.target.value;
this.setState(this.state);
this.handleOnSave()
}
handleOnSave = () => {
this.props.ParentFunction(this.state.test);
}
render() {
return (
<div>
<input type="text" onChange={this.handleChange} />
</div>
);
}
}
export default withStyles(s)(Child);
In Reactjs if I have two child components of an App component, can I take input from one component and output it in the other child component?
class App extends Component{
render(
<Input/>
<Output/>
)
}
Input = () => { //input }
Output = () => { //output }
It's simple. Use the same state value for both components in the parent component:
class App extends Component{
constructor(props){
super(props);
this.state = {
value: ''
}
onValueChange = thisonValueChange.bind(this);
}
onValueChange(e) {
e.preventDefault();
setState({
value: e.target.value
});
}
render(){
return(
<Input value={this.state.value} onChange={this.onValueChange} />
<Output value={this.state.value}/>
);
}
}
Input = (props) => {
<input value={props.value} onChange={props.onValueChange}>
}
Output = (props) => <div>{props.value}</div>);
You can handle the data in the App component via state by passing a handler down to the Input component
and then pass the state value down to the Output component like
const Input = props => <input onChange={props.handleChange} />
const Output = props => <span>{props.data}</span>
class App extends Component {
state = {data:""}
handleChange = e => {
this.setState({ data: e.target.value })
}
render() {
return (
<div>
<Input handleChange={this.handleChange} />
<Output data={this.state.data} />
</div>
)
}
}
`export class Parent extends React.Component{
constructor(props){
super(props);
this.state={
name:'',
sendData:false
}
}
render(){
return (<div><input type="text" onChange={(event)=>
{this.setState({
name:event.target.value,
})
})
/>
//sendData can be made true on a button click
{this.state.sendData ?(<div><Child name={this.state.name}
/>
</div>):null}
</div>)}
}`
Display the data of Parent in the child component.
`export class Child extends React.Component{
render(){
return (<div>Name is :{this.props.name}</div>)
}
}`
I have build an input-field component and need to access its value from parent component. I tried something like document.getelementById(id).value, but it'll return null as value.
Parent component:
import StateBox from './StateBox.js';
import React, { Component } from 'react';
export default class AdressenListe extends Component {
render() {
let filteredAdressen = this.props.adressen.filter(
(asingle) => {
return asingle.Firma.toLowerCase().indexOf(document.getElementById('Firma').value.toLowerCase()) !== -1;
}
);
var anzahl = filteredAdressen.length;
return (
<div>
<StateBox id="Firma" />
<StateBox id="PLZ" />
<li>
</li>
</div>
);
}
}
Input-field component:
import React, {Component} from 'react';
export default class StateBox extends Component {
//constructor input field
constructor() {
super();
//equal to object
this.state = {
search: ''
};
}
updateSearch(event) {
console.log(event.target.value);
this.setState({search: event.target.value});
}
render(){
return(
<form className="StateBox">
<input type="text" value={this.state.search} onChange={this.updateSearch.bind(this)}/>
</form>
);
}
}
You can declare the state in the parent component and pass function to update that in child component
class Parent extends Component {
this.state = {
value: ''
}
changeValue = (value) => {
this.setState({value});
}
render() {
return <Child inputValue={this.state.value} changeValue={this.state.changeValue} />
}
}
class Child extends Component {
render() {
<input value={this.props.inputValue} onChange={(e) => this.props.changeValue(e.target.value)} />
}
}
If you want to access the value of a child component, you need to lift the state up and make the child component controlled, because that's the way you should code in react.
Taking your code as base:
class AdressenListe extends Component {
constructor() {
super();
this.state = {
Firma: ''
};
}
changeValue (Firma) {
this.setState({Firma});
}
render() {
let filteredAdressen = this.props.adressen.filter(
(asingle) => {
return asingle.Firma.toLowerCase().indexOf(this.state.Firma.toLowerCase()) !== -1;
}
);
return (
<div>
<StateBox inputValue={this.state.Firma} changeValue={this.changeValue.bind(this)} />
</div>
);
}
}
Note how I pass down the necessary props and the state is managed by the parent.
class StateBox extends Component {
render () {
return <input type="text" value={this.props.inputValue} onChange={(e) => this.props.changeValue(e.target.value)} />
}
}