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>
);
}
}
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"));
Is it possible to create a method in Parent class in React and then pass it on to the Child and use it there.
So basically I would create a button in my Parent class, pass the function on to the Child and when the Button is clicked, the child will know about it and Parent will not really care for it?
class App extends Component {
clickMade = () => {
//This should be left empty
};
render() {
return (
<div className="App">
<Button onClick={this.clickMade}>Click me </Button>
<Child clickMade={this.clickMade} />
</div>
);
}
}
export default App;
And the Child:
class Child extends Component {
constructor(props) {
super(props);
this.handleClick = this.props.clickMade.bind(this);
}
handleClick = () => {
console.log("Click in child");
}
render() {
return null;
}
}
export default Child;
And a sandbox for this: CodeSandbox
App.js
class App extends Component {
clickMade = () => {
this.childRef.handleClick();
};
render() {
return (
<div className="App">
<Button onClick={this.clickMade}>Click me </Button>
<Child
ref={ref => {
this.childRef = ref;
}}
/>
</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);
I have two components. the App component which is the parent component and the Btn component which is the child component. How can i change the value of property text from the Btn component?
export default class App extends Component<Props> {
constructor() {
super();
this.text = 'testing';
this.onClicked = this.onClicked.bind(this);
}
onClicked() {
this.text = 'changed';
}
render() {
return (
<View style = { styles.container }>
<Text style = { styles.welcome }> { this.text } </Text>
<Btn />
</View>
);
}
}
class Btn extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Button
title = 'Button'
onPress = { ? }
/>
)
}
}
You can pass the parent component's onClicked function as a prop to the child component.
export default class App extends Component<Props> {
...
render() {
return (
<View style = { styles.container }>
<Text style = { styles.welcome }> { this.text } </Text>
<Btn onClicked={this.onClicked}/>
</View>
);
}
}
class Btn extends Component {
...
render() {
return (
<Button
title = 'Button'
onPress = {this.props.onClicked}
/>
)
}
}
You are holding your text value in the wrong place. Hold it in your state. constructor runs once in the initial render and it does not run again like that. But, as a React way, if you hold your data in your state, whenever state changes your component rerenders and you see the updated data.
Then, you can pass your onClick handler to the child component and use it there. Here is the working snippet. I used class-fields so no need to write a constructor and an arrow function (no need to bind it).
class App extends React.Component {
state = {
text: "",
}
onClick = () =>
this.setState({text: "foo bar" });
render() {
return (
<div>
<p>Text is now: { this.state.text } </p>
<Btn onClick={this.onClick} />
</div>
);
}
}
const Btn = ( props ) => (
<button onClick={props.onClick}>Click</button>
)
ReactDOM.render(
<App />,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
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);
}
}