How to transfer data from react child component to parent component - javascript

I need to figure out how to transfer the data i receive in a child component to the one in parent component. I need to set the console log i receive in the child to transfer to the parent component state.
Currently I have:
Child Comp:
import Picker from 'react-giphy-component'
import React, { Component, PropTypes } from 'react'
class AddGif extends Component {
log (gif) {
console.log(gif.original.mp4)
}
returnedGifObject = gif ;
render () {
return (
<div>
{/* <button></button> */}
<Picker onSelected={this.log.bind(this)} />
</div>
)
}
}
export default AddGif;
parent element
class PostBox extends Component {
constructor(props){
super(props)
this.state = {
title: null,
postBody: null,
giphyUrl: null,
displayGifPicker: false
}
}
getGifState = (selectedUrl) => {
this.setState({ giphyUrl: selectedUrl})
}
render () {
const {title, postBody} = this.state
const displayGifPicker = this.state.displayGifPicker
return (
<Grid item xl={8}>
{/* <Card className={classes.card} style={mt4}> */}
<Card style={mt4}>
<CardContent >
<PostInput onChange={this.handleInputChange} onSubmit={this.handleSubmit}/>
{displayGifPicker ? (<AddGif selectedGif = {this.getGifState} />) : (<Button size="small" onClick={this.displayGifPicker} ><button>Add Gif</button></Button>)}
<CardActions>
{/* <Button size="small">Submit VH5</Button> */}
</CardActions>
</CardContent>
</Card>
</Grid>
)
}
}

You passed the function prop to children component. Then In Children component just call it :
log = (gif) => {
const { selectedGif } = this.props
console.log(gif.original.mp4)
selectedGif(gif.original.mp4)
}

Related

We need to add a counter, in which, after clicking on the Badge button, it displays the number of items in the cart

We need to add a counter, in which, after clicking on the Badge button, it displays the number of items in the cart. Tell me how to pass it through the class component. I have a Navbar class component, it has a Badge that should show how many products have been added to the cart, and there is a Cart class that needs to be passed to Navbar as props. Tell me how to pass it through the class component.
<Badge count={this.state.totalItems}>
<ShoppingCartOutlined />
</Badge>
here I feed yogo through the constructor
class Navbar extends React.Component {
constructor(props){
super(props);
this.state = {
current: "mail",
}
}
handleClick = (e) => {
console.log("click ", e);
this.setState({ current: e.key });
};
render() {
const { t } = this.props;
const { current } = this.state;
return (
<div className="navbar">
<Menu
onClick={this.handleClick}
selectedKeys={[current]}
mode="horizontal"
>
<Menu.Item key="main" icon={<HomeOutlined />}>
{t("menu.home")}
</Menu.Item>
<Menu.Item key="favorites" icon={<HeartOutlined />}>
{t("menu.favorites")}
</Menu.Item>
<Menu.Item key="Faq" icon={<QuestionCircleOutlined />}>
{t("menu.faq")}
</Menu.Item>
</Menu>
<div className="navbar__logo">
CLOTHES
<span>.STORE</span>
</div>
<Menu
onClick={this.handleClick}
selectedKeys={[current]}
mode="horizontal"
className="right-menu"
></Menu>
<div className="button_sign">{t("menu.signup")}</div>
<Badge count={this.state.totalItems}>
<ShoppingCartOutlined />
</Badge>
<div className="navbar_lang">
<SetLanguage />
</div>
</div>
);
}
}
export const Cart = ({ totalItems}) => {
const classes = useStyles();
return (
<>
<AppBar position="fixed" className={classes.appBar} color="inherit">
<div>
<IconButton arial-label="Show cart items" color="inherit">
<Badge badgeContent={totalItems} color="secondary">
<ShoppingCart/>
</Badge>
</IconButton>
</div>
</AppBar>
</>
);
};
If you want to change the value of totalItems in the state of a Parent Component from a Child Component, you can:
Use a state management tool (ex: redux) if your application will grow bigger
If it's a simple case like yours here, you can create a method inside the parent component called increment, pass it as props to the child component and call it there. It will be bound and executed in the context of the Parent Component.
class Navbar extends React.Component {
constructor(props){
super(props);
this.state = {
current: "mail",
totalItems: 0, // add the total to the state
}
}
// Define increment inside the parent component
increment = () => {
this.setState({totalItems: totalItems++})
}
render() {
const { t } = this.props;
const { current } = this.state;
return (
// ...
<Badge count={this.state.totalItems}>
<ShoppingCartOutlined count={this.state.totalItems} increment={this.increment} />
</Badge>
// ...
);
}
}
Then, inside your child component, call that method with a click listener:
export const ShoppingCartOutlined = ({ count, increment }) => {
const classes = useStyles();
return (
<>
<AppBar position="fixed" className={classes.appBar} color="inherit">
<div>
<IconButton arial-label="Show cart items" color="inherit">
<Badge
badgeContent={count}
onClick={increment} // or () => increment()
color="secondary"
>
<ShoppingCart/>
</Badge>
</IconButton>
</div>
</AppBar>
</>
);
};

passing image from list(stateless) component to display(stateful) component --react

//ImagePlayer component
class ImagePlayer extends Component {
constructor(props) {
super(props)
this.state = {
image: [],
selectedImage: '',
}
this.handleImageSelection = this.handleImageSelection.bind(this);
}
handleImageSelection(source){
this.setState({ImageList : source})
}
render() {
return (
<Grid container spacing={3}>
<Grid item xs={8}>
<Paper>
{/* this is the larger div where I want to render the image clicked on the list */}
<ImageList handleImageSelection={this.handleImageSelection}/>
</Paper>
</Grid>
<Grid item xs={4}>
<Paper>
<ImageList />
</Paper>
</Grid>
</Grid>
);
}
}
//ImageList component
onst ImageList = (handleImageSelection) =>{
handleImageSelection=(image)=>{
console.log(image);
}
return(
images.map((image, id) =>
<List>
<ListItem key={id} >
<div>
<ListItemAvatar>
{<img src= {require(`../assets/${image.name}.jpeg`)} alt="thumbnail" onClick={()=>handleImageSelection(require(`../assets/${image.name}.jpeg`))}/>}
</ListItemAvatar>
</div>
<div >)
How to render the image from List component to Class component in React? My list component is list of images and that should appear enlarged in class component when I click on any image on the list.
I first defined the state: this.state ={ imageSelected: ''}
then, setState for the same.
Also passed handleImageSelection as a function in list component, but it says
'handleImageSelection' is not a function
onClick={()=> props.handleImageSelection()} //errr: not a function
If both your list and display component are wrapped by common parent, you may lift necessary state (e.g. chosen image id) as follows:
const { Component } = React,
{ render } = ReactDOM,
rootNode = document.getElementById('root')
const imageList = [
{id:0, name: 'circle', imgSrc: `data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSI1MCIgY3k9IjUwIiByPSI1MCIvPjwvc3ZnPg==`},
{id:1, name: 'triangle', imgSrc: `data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNTAsMCBMMTAwLDEwMCBMMCwxMDAgeiIvPjwvc3ZnPg==`},
{id:2, name: 'square', imgSrc: `data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMCwwIGgxMDAgdjEwMCBoLTEwMCB6Ii8+PC9zdmc+`},
]
const List = ({images, onSelect}) => (
<ul>
{
images.map(({imgSrc, name, id}) => (
<li key={id} onClick={() => onSelect(id)}>
<img className="thumbnail" src={imgSrc} alt={name}/>
</li>
))
}
</ul>
)
class Display extends Component {
render (){
const {imgSrc,name} = this.props.image
return (
<img className="fullsize" src={imgSrc} alt={name} />
)
}
}
class App extends Component {
state = {
chosenImg: null
}
images = imageList
onSelect = _id => this.setState({
chosenImg: this.images.find(({id}) => id == _id)
})
render(){
return (
<div>
<List images={this.images} onSelect={this.onSelect} />
{ this.state.chosenImg && <Display image={this.state.chosenImg} />}
</div>
)
}
}
render (
<App />,
rootNode
)
.thumbnail {
max-width: 50px;
cursor: pointer;
}
.fullsize {
width: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>

How to pass props from child component to parent component to another child component in ReactJS?

I'm currently creating a search bar where App is the parent and Header, Home are the children. I'm trying to pass the input from Header to Home via App but it seems that when I try to load in {this.state.searchValue} it does nothing.
I'm lost of where I am wrong in my code. I'm also using Route to route the props from Header to Home.
Here is my code:
Header.js (Child 1)
class Header extends Component {
constructor(props) {
super(props);
this.state = {
search: "",
};
}
onChange = (event) => {
this.setState({ search: event.target.value });
};
submitSearch = (event) => {
event.preventDefault();
console.log(this.state.search);
this.props.passSearchData(this.state.search);
};
render() {
return (
<React.Fragment>
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<form className="form-inline">
<input
className="form-control mr-sm-2"
type="text"
placeholder="Search"
onChange={this.onChange}
/>
<button
className="btn btn-danger"
type="submit"
onClick={this.submitSearch}
>
Search
</button>
</form>
</nav>
</React.Fragment>
);
}
}
export default Header;
App.js (Parent)
class App extends Component {
constructor() {
super();
this.state = {
searchValue: "",
};
}
handleSearchData = (search) => {
this.setState({ searchValue: search });
};
componentDidMount() {
this.props.getItems();
}
render() {
return (
<div className="App">
<Router>
<Header passSearchData={this.handleSearchData} />
<Route
exact
path="/"
render={(props) => (
<Home {...props} searchValue={this.state.searchValue} />
)}
/>
</Router>
<Footer />
</div>
);
}
}
Home.js
class Catalog extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<div>
<p>{this.props.searchValue}</p>
</div>
);
}
}
I think using react context better for this problem, because passing state between routes quite painful
First u declare your own Provider to act as intermediary between components.
The context will save all the application state. and to consume at your components, simply use useContext and pass the Context u want to use, at this useCase, i call it AppContext. by using the same context, your components get the same state and trigger update immediately
The solution i provide is using functional component. If u are using class Component, just simply create a functional component, then pass the context to the class component
import React, { useContext, useState } from 'react'
const AppContext = React.createContext({})
const AppProvider = props => {
const [currentState, setCurrentState] = useState(null)
const handleState = value => {
setCurrentState(value)
}
const contextValue = { handleState, currentState }
return (
<AppContext.Provider value={contextValue}>
{props.children}
</AppContext.Provider>
)
}
const Child1 = props => {
const { handleState } = useContext(AppContext)
const handleClick = e => {
handleState(e.target.values)
}
return (
<button onClick={handleClick}>Change State</button>
)
}
const Child2 = props => {
const { currentState } = useContext(AppContext)
return (
<h1>{currentState}</h1>
)
}
const Parent = props => {
return (
<Router>
<AppProvider>
<Route component={Child1} />
<Route component={Child2} />
</AppProvider>
</Router>
)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

How to update react context in child elements

Hi i have problem with context in react. I need to update context data after i fetch some data in child component:
Here is my app code
export default class App extends Component {
constructor(props) {
super(props);
this.state = { loggedInUser: null };
this.onLogin = this.onLogin.bind(this);
this.onLogout = this.onLogout.bind(this);
}
onLogin(value) {
this.setState({ loggedInUser: value });
}
onLogout(value) {
this.setState({ loggedInUser: null });
}
render() {
let content = null;
if (this.state.loggedInUser == null) {
content = <div> <LoginScreen onLogin={this.onLogin} /> </div>
}
else {
content = <div> <Application onLogout={this.onLogout} /> </div>
}
return (
<MuiThemeProvider theme={ApplicationTheme}>
<Context.Provider value={{
user:this.state.loggedInUser,
updateUser: (user) =>{this.user=user},
company: null,
updateCompany:(company) => {this.company=company},
role: null,
updateRole:(role) => {this.role = role},
}}>
{content}
</Context.Provider>
</MuiThemeProvider>
);
}
From this component i go to login screen and AFTER that in component where i should select role. In this component i need update role data in context. How to do this please?
export class RoleSelector extends Component {
static displayName = RoleSelector.name;
static contextType = Context;
render() {
console.log(this.context);
this.context.updateCompany(1);
console.log(this.context);
console.log("Afterext)");
let companies = this.context.userCompanies.map(u =>
<Grid item lg={6} xs={12} key={u.company.id}>
<UserCompany userCompany={u}> </UserCompany>
</Grid>
);
return (
<Container className="roleSelector">
<Context.Consumer>
<Grid container direction="column" justify="center" alignItems="center" alignContent="center"
spacing={1}>
<Box my={2}>
<Typography variant="h1" align="center">Vyberte typ uživateľa</Typography>
</Box>
<Grid container className="company" justify={"center"}>
{companies}
</Grid>
</Grid>
</Context.Consumer>
</Container>
);
}
}
I tried to pass method to update data in context but it return unchanged context. (Data has same values after using updateCompany in my example)
Thx for help
Assuming that you have const Context = React.createContext(), I'll do something like this:
will add company and role to App state
will add methods for updating company and role and bind them in App constructor.
pass all 4 items to Context.Provider value. It would look like something like this:
value={{
user: this.state.loggedInUser,
updateUser: this.updateUser,
company: this.state.company,
updateCompany: this.updateCompany,
role: this.state.role,
updateRole: this.updateRole,
}}
in the RoleSelector component, you'll have something like this:
<Context.Consumer>
{({user, updateUser, company, updateCompany, role, updateRole}) => (...your jsx)}
</Context.Consumer>

getting the value of child component

I'm trying to get the value of child component yet not successful. Here what I am working on ...
import React from "react";
import Tooltip from "rc-tooltip";
import Slider, { Range } from "rc-slider";
const Handle = Slider.Handle;
const handle = props => {
const { value, dragging, index, ...restProps } = props;
return (
<Tooltip
prefixCls="rc-slider-tooltip"
overlay={value}
visible={dragging}
placement="top"
key={index}
>
<Handle value={value} {...restProps} />
</Tooltip>
);
};
const Slider = props => {
return (
<div>
<div style={{ width: 300, margin: 30 }}>
<p>{this.props.title}</p>
<Slider min={0} max={10} defaultValue={5} handle={handle}/>
</div>
</div>
);
};
export default Slider;
Main App.js
import Slider from '.....'
class App extends Component{
constructor(props){
super(props);
this.state = {
val: 0
}
}
render() {
return(
<Slider onChange={this.state.value} />
)
}
}
I am looking to get the value to be updated to this App.js state as the slider is being dragged. onChange is not updating the state. How should I modify so that slider value gets updated on this.state.value.
The Slider component from rc-slider has an onChange prop event which is a function. You need to pass this method to slider and update the state instead of just passing the state value
import React from "react";
import Tooltip from "rc-tooltip";
import Slider, { Range } from "rc-slider";
const Handle = Slider.Handle;
const handle = props => {
const { value, dragging, index, ...restProps } = props;
return (
<Tooltip
prefixCls="rc-slider-tooltip"
overlay={value}
visible={dragging}
placement="top"
key={index}
>
<Handle value={value} {...restProps} />
</Tooltip>
);
};
const Slider = props => {
return (
<div>
<div style={{ width: 300, margin: 30 }}>
<p>{this.props.title}</p>
<Slider min={0} max={10} defaultValue={5} onChange={props.onChange} handle={handle}/>
</div>
</div>
);
};
export default Slider;
class App extends Component{
constructor(props){
super(props);
this.state = {
val: 0
}
}
onChange=(value) => {
this.setState({val: value});
}
render() {
return(
<Slider onChange={this.onChange} />
)
}
}
Here is the Live code
https://codesandbox.io/s/n9y97y55kp
Let me know if you have any doubts
You just have to pass the event from child to parent component to update the values.
according to rc-slider document, you should pass a function to Slider onChange.
import Slider from '.....'
class App extends Component {
constructor(props) {
super(props);
this.state = {
val: 0
}
}
handleSliderChange = (value) => {
console.log(value) // maybe a string or a object
this.setState({val: value})
}
render() {
return (
<Slider onChange={this.handleSliderChange} />
)
}
}
above code should work

Categories

Resources