Passing checkbox list value from child to parent - reactjs

I am creating search form with checkboxes and call api URL. I need advise on how to pass selected checkboxes value from child component back to parent component and update the selected value string state. Thanks.
//CheckboxTest.js
import React,{Component} from 'react';
const data=[
{checked:false, value:'location A'},
{checked:false, value:'location B'}
];
class CheckboxTest extends Component{
state={items:[]};
onCheckChange=(idx)=>{
const items = this.state.items.concat();
items[idx].checked = !items[idx].checked;
this.setState({items});
this.props.onChange(this.state.items);
};
render(){
return (
<div>{data.map(item=>(<div>
<input type="checkbox" checked={item.checked} onChange= {item.onCheckChange} />
{ item.value }
</div>))}</div>
);
}
}
export default CheckboxTest;
//App.js
import CheckboxTest from './CheckboxTest';
class App extends Component {
state={
items:[],
itemchecked
};
componentDidMount(){
//call api
this.runSearch({items});
}
//handle checkbox changes
handleChange(id) {
//how to set items state here ???
this.runSearch(id);
}
render(){
return (
<div className="App">
<form>
<CheckboxTest onChange={this.handleChange} checked={this.itemchecked} />
</form>
</div>
);
}
}
export default App;

In React there is a one-way data flow. All data flows from parents to children. As such, the parent has to own the function (as you have done with your handleChange-function) and the child has to run that function. This last part you have not done.
You need to use the props of the child to access the function you have passed down from the parent. Read more here:
https://reactjs.org/docs/faq-functions.html

Related

React Adding two parents for a child component

State is the smart component which store all the states of child components
import React from 'react';
import TextArea from './Components/TextArea';
class State extends React.Component {
constructor(props) {
super(props);
this.state = {
name: ''
}
this.myChangeHandler = this.myChangeHandler.bind(this)
}
myChangeHandler = (event) => {
event.preventDefault();
this.setState({
[event.target.name]:event.target.value
});
}
render() {
return (
<div>
{/* Change code below this line */}
<TextArea name = {this.state.name}
myChangeHandler = {this.myChangeHandler}/>
{/* Change code above this line */}
</div>
);
}
};
export default State;
Now TextArea is the child component which share the input value to state.
import React from 'react';
import '../style.css';
class TextArea extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<input type="text" onChange= {this.props.myChangeHandler} name="name" value={this.props.name}></input>
<h1>Hello, my name is:{this.props.name} </h1>
</div>
);
}
};
export default TextArea;
There are several child components that send the data to state component.
so the app component is used to order the child component.
I need two parents for a child component. please see the image enter image description here
import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom'
import './App.css';
import TextArea from './Components/TextArea'
function App() {
return (
<div className="App">
<BrowserRouter>
<Route path = "/new" component= {TextArea} />
</BrowserRouter>
</div>
);
}
export default App;
You can't have two "direct" parent for a single component but you can have multiple indirect parents.
Example:
App is the parent of State
State is the parent of TextArea
App is also a parent of TextArea but not a direct one.
This means that you can pass props (data and functions) from the top parent to all of his children.
If you need to pass a function from App to TextArea you need to pass it by State.
Here a tutorial on how to do it.
You can also use the Context and here's a tutorial on how to do it.

Get value from input component and use it in another component in React

I'm new to React and have this simple code example where I simply need to take value from input and show the value back.
class App extends React.Component {
constructor(props){
super(props);
this.state = { word : ""};
this.onClick = this.onClick.bind(this);
}
onClick(e){
this.setState({word : /* how to obtain input value?? */});
}
render() {
return (
<>
<form>
<input type="text"/>
<button onClick={this.onClick}>Say it!</button>
</form>
<div>
{this.state.word}
</div>
</>
);
}
}
I know react want's me to use component state as a way to propagate information from parent component to it's children. What I don't know is how I should obtain state of a children to be used in another children.
I believe this should be doable in react in simple manner as the equivalent way of doing it using pure DOM or JQuery would also be very simple (one or two lines of code).
You can use createRef
import React, { createRef } from "react";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = { word: "" };
this.onClick = this.onClick.bind(this);
}
textInput = createRef();
onClick(e) {
this.setState({ word: this.textInput.current.value });
}
render() {
return (
<div className="App">
<form>
<input ref={this.textInput} type="text" />
<button onClick={this.onClick} type="button">
Say it!
</button>
</form>
<div>{this.state.word}</div>
</div>
);
}
}
export default App;
check here CodeSandBox
A few things here. First I don't see children as you mention. Moreover, you say obtain state of a children to be used in another children. You have just one parent component here. Then, you are using a <form> which means a button inside will submit the values so you need the escape hatch of e.preventDefault(). Finally, if you must use a class based component instead of functional component, you don't need any more constructor and you can bind your functions with an arrow function. Here is a working example of what I presume you are asking: https://codesandbox.io/s/sleepy-minsky-giyhk

How to store user input data in console log on form submit from child to parent component?

I have my child components within my parent component and I would like to be able to console log what data a user has submitted. However, being new to react I am not sure how I should do this?. Would love some help!
import React, { Component } from 'react';
import './App.css';
import PageOne from './Components/PageOne';
import PageTwo from './Components/PageTwo';
import PageThree from './Components/PageThree';
import PageFour from './Components/PageFour';
import PageFive from './Components/PageFive';
import PageSix from './Components/PageSix';
import PageSeven from './Components/PageSeven';
import { Input, Dropdown, TextArea, Form, Button, Header } from 'semantic-
ui-react'
class App extends Component {
render() {
return (
<div className="App">
<PageOne />
<PageTwo />
<PageThree />
<PageFour />
<PageFive />
<PageSix />
<Button>
Submit Form
</Button>
<br/>
<br/>
</div>
)
}
}
export default App;
We can pass a callback through the Parent component as props to Child and invoke it after handling the form submission.
You cant really "store" it in the console, What are you trying to do exactly ?
Do you want to save the user submitted data to use later in a part of your App? if so you could pass a call back to set the state in your Parent component with the data submitted, this way you can share the data with other Child components through the Parent state
The important thing to understand here is that we pass callbacks as props to Child components when we need to pass data to Parent components and save it to our state this way our Parent can share the state with the rest of our App.
function Parent() {
const logAfterSubmit = data => {
console.log("user submitted data", data);
};
return (
<div className="App">
<Child logAfterSubmit={logAfterSubmit} />
</div>
);
}
function Child({ logAfterSubmit }) {
const [input, setInput] = useState("");
const handleSubmit = e => {
e.preventDefault();
// do something with the data
// call our function from parent with the data
logAfterSubmit(input);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" onChange={e => setInput(e.target.value)} />
<button type="submit">Submit</button>
</form>
);
}
SandBox
Welcome to stackoverflow. React is an amazing tool for developing websites. Unique to React is a concept called "state" which is essentially what you're looking for. "State" is React's ability to keep track of data and use it accordingly. In your case, you want to record what a user submits in your child component.
Let's consider the following code:
class Parent extends React.Component{
//define state here which is typically an empty object
state = {
text: ""
}
//this is an event handler we have set up to take the data from state
handleOnSubmit = () => {
event.prevent.default() //stops page from refreshing
console.log(this.state.text)
}
//event handler that is triggered every time a user makes a change to the input
handleOnChange = (event) => {
//unique method in React that lets you update the component state
this.setState({
text: event.target.value
})
}
//all class-based components are called with render
render(){
return(
//we can pass down event handlers/functions we've defined into child components.
<Child handleOnChange={this.handleOnChange} handleOnSubmit={this.handleOnSubmit}/>
)
}
}
Now for our Child Component
//this is known as a stateless-functional component. no need to keep track of state.
const Child = (props) => {
return(
<form onSubmit={props.handleOnSubmit}>
//onChange is a unique-event listener that gets called anytime characters changes inside an input tag. So in this case we update our Parent's state every time we type.
<input onChange={props.handleOnChange} name="text" />
</form>
)
}
So a high-level summary of this. We set up a parent-component and defined functions inside of it that will help keep track of "state" or data. Then we pass down those functions as properties to our Child component. Our child component uses those functions and when they are called, they will update the state in our Parent component. Thus giving you a controlled-input flow, where you are constantly keeping track of data coming into your forms.

How to communicate between two components in Reactjs

I'm a newbie in React. Why can't my data pass to another component?? My idea is after the user select option tag, then it will load some audio files based off the selection. But it's not working. What did I miss?
Or is there a better to do it?
This is my dropdown component
import React from 'react';
import Playlist from './Playlist/Playlist.js';
class Dropdown extends React.Component {
constructor (props) {
super(props);
this.state = {value: "1"};
this.handleChange = this.handleChange.bind(this);
this.handleEnter = this.handleEnter.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
console.log("Hello");
console.log(event.target.value);
console.log(typeof(event.target.value));
}
handleEnter(event) {
alert("Clicked: " + this.state.value);
event.preventDefault();
}
render (){
return (
<form onSubmit={this.handleEnter} >
<label>
<div className="langueageSelection">
<Playlist langueageSelection={this.handleChange.bind(this)} />
<select value={this.state.value} onChange={this.handleChange} >
<option value=""> Please select a language </option>
<option value="1"> English (American) </option>
<option value="2"> Chinese (Mandarin) </option>
</select>
</div>
</label>
<input type="submit" value="Enter" className="EnterButton"/>
</form>
);
}
}
export default Dropdown;
This is my playlist component.
import React from 'react';
class Playlist extends React.Component {
handleChange({target}){
this.props.langueageSelection(target.value)
}
render() {
if (this.props.langueageSelection === "1"){
console.log("English");
}
else if(this.props.langueageSelection === "2"){
console.log("Chinese");
}
return (
<div> Hi</div>
);
}
}
export default Playlist;
This is my entry component:
import React from 'react';
import mind_zebra from '../../images/MindScribe-zebra.png';
import Dropdown from '../Dropdown/Dropdown.js';
class Entry extends React.Component {
state = { hideZebraPic : false};
onClickHandler = () => {
this.setState( prev => ({ hideZebraPic : !prev.hideZebraPic }));
};
render() {
if (this.state.hideZebraPic) {
return (
<div>
<Dropdown />
</div>
);
} else {
return (
<div>
<img src={mind_zebra} onClick={this.onClickHandler} className="MindZebraPic" alt="zebra"/>
</div>
);
}
}
}
Here's my structure of directory:
src
|
audio
- English audios
- Chinese audios
components
|
Dropdown
|
playlist
- playlist.js
dropdown.js
|
Entry
|
entry.js
|
Home
|
App.js
Or is there a better to do it?
Please take a look Single source of truth and its implementation by Redux or MobX
Maybe could you please specify what exactly does not work? Playlist does not receive selected language? Should it?
Because now, it looks like this:
<Playlist langueageSelection={this.handleChange.bind(this)} />
You pass function to Playlist, right? And as I understand, role of Playlist is to render some content, based on selections made in parent component, which is Dropdown? Why would you pass a function to the children component? An why would you decorate it with .bind(this)? You've bound "it" already in constructor (which is a "Dropdown" as I understand).
If you really need to get it working as it is:
In Dropdown, pass the "value" as a prop to child
<Playlist langueageSelection={this.state.value} />
In Playlist, I'm not quite sure if you need this function to be passed.
import React from 'react';
class Playlist extends React.Component {
render() {
if (this.props.langueageSelection === "1"){
console.log("English");
}
else if(this.props.langueageSelection === "2"){
console.log("Chinese");
}
return (
<div> Hi</div>
);
}
}
export default Playlist;
For further development:
I think you could get in touch with some programming patterns of React. Please make some research on "stateless components updating parent's state". I don't know your idea about whole application, but I feel that Playlist should not be a child of a Dropdown. I would propose something like this:
Dropdown and Playlist are siblings. Let's say that they parent App. App is stateful component. Dropdown and Playlist are stateless components. App passes function ChangeLanguage to the Dropdown. ChangeLanguage is bound to App. Function ChangeLanguage handles selection of lang in Dropdown, takes event and updates App state with event.target.value. Then App passes its state to Playlist as a prop.
I hope that I understood your issue right.

Get another component input value React js

I have two components one is app component and other one is sidebar component i have been using input field in side bar and i want to get the value of that input field in my app component on click how this could be possible ?
You can try lifting the state up.
Create a new component that will contain your two components. In that new component, create a function that you will pass as props inside the sidebar component.
class ContainerComponent extends React.Component {
constructor() {
super();
this.state = {
valueThatNeedsToBeShared: ''
}
}
handleChange(e) {
this.setState({valueThatNeedsToBeShared: e.target.value})
}
render() {
return (
<div>
<AppComponent value={this.state.valueThatNeedsToBeShared} />
<SidebarComponent handleChange={this.handleClick.bind(this)} value={this.state.valueThatNeedsToBeShared} />
</div>
)
}
}
const SidebarComponent = ({handleChange, value}) => <aside>
<input value={value} onChange={handleChange} />
</aside>
const AppComponent = ({value}) => <div>
value from sidebar: {value}
</div>
In pure react it is possible by adding callback from one component and use it into parent component to change their state and then send input value from parent's state to props of your second component

Resources