I want to pass data from a child to parent REACT JS - reactjs

I have a function that selects a country from a dropdown. I have put it in a file by itself. And then on my Dashboard.js I just call the funtion to appear. But how can I get the value from the Dashboard.js?
CountrySelector.js
import React, { useState, useMemo } from 'react'
import Select from 'react-select'
import countryList from 'react-select-country-list'
function CountrySelector() {
const [value, setValue] = useState("")
const options = useMemo(() => countryList().getData(), [])
const changeHandler = value => {
setValue(value)
}
const style = {
display: "inline-block",
width: "300px"
};
return <div style={style}><Select options={options} value={value} onChange={changeHandler} /></div>
}
export default CountrySelector;
Dashboard.js
import CountrySelector from '../util/CountrySelector';
const Dashboard = () => {
return(
<div>
<CountrySelector/>
</div>
);
};
export default Dashboard;
I know props doesn't work because you pass data from parent to the child. And I want to pass data from child to the parent. Any help is appreciated.

Put your state in your parent component, and pass them as props to your child component
import { useState, useMemo } from 'react';
import CountrySelector from '../util/CountrySelector';
import countryList from 'react-select-country-list';
const Dashboard = () => {
const [value, setValue] = useState('');
const options = useMemo(() => countryList().getData(), []);
return (
<div>
<CountrySelector value={value} setValue={setValue} options={options} />
</div>
);
};
export default Dashboard;
import Select from 'react-select';
function CountrySelector({ value, setValue, options }) {
const style = {
display: 'inline-block',
width: '300px',
};
return (
<div style={style}>
<Select options={options} value={value} onChange={setValue} />
</div>
);
}
export default CountrySelector;

Related

how to extract data from react components in a loop?

I have a bunch of filtering components that developers can use. For example TextFilter.js, OptionsFilter.sj, NumericFilter.js
And this is the code of TextFilter.js
import TextField from '#material-ui/core/TextField';
import { useState } from 'react';
const TextFilter = ({ column, placeholder }) => {
const [value, setValue] = useState('');
return <TextField
onChange={(event, value) => setValue(event.target.value)}
lable={placeholder}
/>
};
export default TextFilter;
Developers use it this way:
import List from '../../Components/Layouts/List';
import TextFilter from '../../Components/Filters/TextFilter';
import NumericFilter from '../../Components/Filters/NumericFilter';
const filters =
<>
<TextFilter column='title' placeholder='Title' />
<NumericFilter column='age' placeholder='Age' min={20} max={130} />
</>
cons SampleList = (props) => {
return (
<ListComponent
filters={filters}
/>
);
};
Now I'm stuck on how to extract values from these filters. How can I extract values?
You should handle child's value in it's parent:
child:
import TextField from "#material-ui/core/TextField";
const TextFilter = ({ column, placeholder, changed }) => {
return (
<TextField
onChange={(event) => changed(event.target.value)}
placeholder={placeholder}
/>
);
};
export default TextFilter;
parent:
import TextFilter from "./TextFilter";
export default function App() {
const handleChanged = (value) => {
console.log(value);
};
return (
<div className="App">
<TextFilter
column="title"
placeholder="Title"
changed={(value) => handleChanged(value)}
/>
</div>
);
}

How to get acces to a child useState in React?

I'm trying to done a form in react that have subcomponents for uploaded images (to do a preview and do it more beautyfull) but the thing is that I can't access to the useState of the child where is the image that I need to send to de backend.
Here is the code of the subcomponent and in the useState I need to acces throught the parent to the image:
import React, { useState, Fragment } from "react";
import {
Layout,
Container,
BoxUpload,
ContainerUploadImage,
TextUploadImage,
LabelUploadImage,
ImagePreview,
} from "./ImageUploadElements";
import UploadPhoto from "../../../images/upload.svg";
import CloseIcon from "../../../images/close.svg";
const ImageUpload = ({text}) => {
const [image, setImage] = useState("");
const [isUploaded, setIsUploaded] = useState(false);
const handleImageChange = (e) => {
if (e.target.files && e.target.files[0]) {
let reader = new FileReader();
reader.onload = (e) => {
setImage(e.target.result);
setIsUploaded(true);
};
reader.readAsDataURL(e.target.files[0]);
}
};
return (
<Layout>
<Container>
<h2>{text}</h2>
<BoxUpload>
<div className="image-upload">
{isUploaded ? (
<ImagePreview>
<img
className="close-icon"
src={CloseIcon}
alt="CloseIcon"
onClick={() => {
setIsUploaded(false);
setImage(null);
}}
/>
<img
src={image}
className="uploaded-image"
draggable={false}
alt="progress-uploaded"
/>
</ImagePreview>
) : (
<Fragment>
<LabelUploadImage htmlFor="upload-input">
<ContainerUploadImage
src={UploadPhoto}
alt="Upload Icon"
draggable={false}
/>
<TextUploadImage>Click to upload image</TextUploadImage>
</LabelUploadImage>
<input
type="file"
name="upload-input"
accept=".jpg,.jpeg,.gif,.png,.mov,.mp4"
onChange={handleImageChange}
/>
</Fragment>
)}
</div>
</BoxUpload>
</Container>
</Layout>
);
};
export default ImageUpload;
And here in that upload form component is where I need to get acces to this image to send it with axios to backend:
import React, { Fragment, useState } from "react";
import {
Container,
FormWrap,
FormContent,
Form,
FormH1,
FormLabel,
FormInput,
FormButton,
FormErrorWrap,
FormError,
FormErrorText,
PhotoWrap
} from "./UploadElements";
import ImageUpload from "../ImageUpload";
import { frontPhotoText, sidePhotoText, backPhotoText } from "./Data";
const Upload = () => {
const [weight, setWeight] = useState("");
const [uploadErrors, setUploadErrors] = useState([{}]);
const upload = (e) => {
e.preventDefault();
// Here will go the axios peticiĆ³n with the wight and the three images uploaded.
}
return (
<Fragment>
<Container>
<FormWrap>
<FormContent>
<Form onSubmit={upload}>
<FormH1>Upload New Progress</FormH1>
<FormLabel htmlFor="weight">Weight</FormLabel>
<FormInput
onChange={(e) => setWeight(e.target.value)}
type="number"
value={weight}
id="weight"
required
/>
<PhotoWrap>
<ImageUpload {...frontPhotoText}/>
<ImageUpload {...sidePhotoText}/>
<ImageUpload {...backPhotoText}/>
</PhotoWrap>
<FormErrorWrap>
{uploadErrors ? (
uploadErrors.map((err, index) => (
<FormError key={index}>
<FormErrorText>{err.msg}</FormErrorText>
</FormError>
))
) : (
<Fragment></Fragment>
)}
</FormErrorWrap>
<FormButton>Upload</FormButton>
</Form>
</FormContent>
</FormWrap>
</Container>
</Fragment>
);
};
export default Upload;
But I don't know how can I get this images throught the parent, if anyone can help I'll be very gratefull, thanks!!!
You can use a combination of forwardRef and useImperativeHandle to expose out a function from the child component that a parent component can invoke.
Child - Import and decorate the child component with forwardRef and use the useImperativeHandle to expose a getImage function that returns the current image state.
import React, { useState, Fragment, forwardRef } from "react";
...
const ImageUpload = forwardRef(({text}, ref) => {
const [image, setImage] = useState("");
const [isUploaded, setIsUploaded] = useState(false);
useImperativeHandle(ref, () => ({
getImage: () => image,
}));
const handleImageChange = (e) => {
...
};
return (
...
);
});
Parent - Create a React ref to pass to ImageUpload and in the callback access the current ref value and invoke the function.
import React, { Fragment, useState, useRef } from "react";
...
const Upload = () => {
const [weight, setWeight] = useState("");
const imageUploadFrontRef = useRef();
const imageUploadSideRef = useRef();
const imageUploadBackRef = useRef();
const [uploadErrors, setUploadErrors] = useState([{}]);
const upload = (e) => {
e.preventDefault();
const imageFront = imageUploadFrontRef.current.getImage();
const imageSide = imageUploadSideRef.current.getImage();
const imageBack = imageUploadBackRef.current.getImage();
// do with the images what you need.
}
return (
<Fragment>
<Container>
<FormWrap>
<FormContent>
<Form onSubmit={upload}>
...
<PhotoWrap>
<ImageUpload ref={imageUploadFrontRef} {...frontPhotoText} />
<ImageUpload ref={imageUploadSideRef} {...sidePhotoText} />
<ImageUpload ref={imageUploadBackRef} {...backPhotoText} />
</PhotoWrap>
...
</Form>
</FormContent>
</FormWrap>
</Container>
</Fragment>
);
};

How to update Draft Value when click of Save Button?

I have a two Input form and a Paragraph, when I try to change the value of input the paragraph get updated, once the paragraph is updated I am trying to edit the paragraph with the help of drafts library, but once I update the paragraph and save it, it doesn't update the paragraph.
Please anyone Help me out to solve the problem
Codesandbox Link : Code
Context API
import React, { useState, createContext } from "react";
export const Contx = createContext();
export const ConProvider = ({ children }) => {
const [customerName, setCustomerName] = useState("");
const [amount, setAmount] = useState("");
const defaultValue = `<p>Hello ${
customerName === "" ? "User" : customerName
},</p>
<p>Please Click on the link below to pay the order - <strong>${amount}</strong> . </p>
<p>Click hear to pay</p>
<br/>
<p>Thanks and Regards</p>
<p>testUser</p>`;
const [draftValue, setDraftValue] = useState(defaultValue);
return (
<Contx.Provider
value={{
defaultValue,
setCustomerName,
setAmount,
customerName,
amount,
setDraftValue,
draftValue
}}
>
{children}
</Contx.Provider>
);
};
homePage
import React, { useContext, useState } from "react";
import ReactDOM from "react-dom";
import { ConProvider, Contx } from "../ContextApi";
import Data from "./Component/Data/Data";
import NewDraft from "./Component/Data/NewDraft";
import Modal from "./Component/Data/Modal";
import "./styles.css";
function App() {
const { defaultValue, setDraftValue, draftValue } = useContext(Contx);
// console.log("defaultValue", defaultValue);
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<div className="App">
<Data />
<Modal handleClose={handleClose} show={show}>
<NewDraft
prsFunc={setDraftValue}
handleClose={handleClose}
defaultValueEmpty={false}
defaultValue={defaultValue}
/>
</Modal>
<div
className="templateStyle p-2"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{
__html: draftValue && draftValue
}}
/>
<button onClick={handleShow}>Edit</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<ConProvider>
<App />
</ConProvider>,
rootElement
);
Input Form
import React, { useContext } from "react";
import { Contx } from "../../../ContextApi";
export default function Data() {
const {
setCustomerName,
setDraftValue,
defaultValue,
setAmount,
customerName,
amount
} = useContext(Contx);
React.useEffect(() => {
setDraftValue(defaultValue);
});
// console.log("fffffff", customerName, amount);
return (
<div>
<input
type="text"
value={customerName}
name="customerName"
placeholder="Enter Customer name"
onChange={(e) => {
setCustomerName(e.target.value);
}}
/>
<input
type="number"
placeholder="Enter Amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
/>
</div>
);
}
DraftJS
import React, { useState } from "react";
import { Editor } from "react-draft-wysiwyg";
import {
EditorState,
convertToRaw,
ContentState,
convertFromHTML
} from "draft-js";
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
import draftToHtml from "draftjs-to-html";
import "./Data.css";
export default function NewDraft({
handleClose,
defaultValue,
defaultValueEmpty,
prsFunc
}) {
const initialState = defaultValueEmpty
? () => EditorState.createEmpty()
: EditorState.createWithContent(
ContentState.createFromBlockArray(convertFromHTML(defaultValue))
);
const [editorState, setEditorState] = useState(initialState);
const onChange = (value) => {
setEditorState(value);
};
const saveData = () => {
prsFunc(draftToHtml(convertToRaw(editorState.getCurrentContent())));
handleClose();
};
// console.log(draftToHtml(convertToRaw(editorState.getCurrentContent())));
return (
<div>
<div style={{ border: "2px solid", padding: "20px" }}>
<Editor
editorState={editorState}
toolbarClassName="toolbarClassName"
wrapperClassName="wrapperClassName"
editorClassName="editorClassName"
onEditorStateChange={(value) => onChange(value)}
/>
<button variant="secondary" onClick={saveData}>
Save
</button>
</div>
</div>
);
}
The problem you are facing is caused by this line in Data component. Every time the component is updated, the draftValue is set to the defaultValue.
React.useEffect(() => {
setDraftValue(defaultValue);
});

How to call functions in composition react-hooks?

I have one base hook(baseHook.js) which has some functions in it. Using composition I am trying to call those functions in child hook(formHook.js).
baseHook.js is as follow
import React, { Fragment, useEffect, useState} from "react";
import PropTypes from "prop-types";
const BaseHook = ({ ...props }) => {
const [show, setshow] = useState(false);
//when hovered on activeInput -->'activeInput' is declared but its value is never read.
const activeInput = (input) => {
setshow(true);
}
return (
<Fragment>
{props.children}
{show ? <div>
<p>Div is visible</p>
</div> : null}
</Fragment>
);
};
BaseHook.propTypes = {
activeInput:PropTypes.func,
};
export default BaseHook;
Now I am trying to use baseHook.js in another formHook.js where onFocus of input activeInput should get called.
import React, { Fragment, useEffect, useState} from "react";
import BaseHook from "components/BaseHook";
const FormHook = ({ ...props }) => {
return (
<BaseHook>
<Fragment>
<input
title= {"Input"}
onFocus={() => activeInput(InputValue)}
value={InputValue}
className="required-field"
/>
</Fragment>
<BaseHook>
);
};
export default FormHook;
activeInput function is not getting called from baseHook hence not able to setshow(true).
I am able to achieve this with react-class components using inheritance but is there way to call functions in composition in react-hooks?

react native : what is the way to change class component to function component in my example?

what is the way to change class component to function component in my example ?
in my example i try to change it to a function component but it doesnt works ,
I would be happy to some help with this issue .
import * as React from 'react';
import { Searchbar } from 'react-native-paper';
export default class MyComponent extends React.Component {
state = {
firstQuery: '',
};
render() {
const { firstQuery } = this.state;
return (
<Searchbar
style={{marginTop: 60}}
placeholder="Search"
onChangeText={query => { this.setState({ firstQuery: query }); }}
value={firstQuery}
/>
);
}
}
import React, {useState} from 'react';
import { Searchbar } from 'react-native-paper';
const MyComponent =()=> {
const [firstQuery, setFirstQuery] = useState("");
return (
<Searchbar
style={{marginTop: 60}}
placeholder="Search"
onChangeText={query => { setFirstQuery(query ) }}
value={firstQuery}
/>
);
}
export default MyComponent;
Do it like this
const MyComponent = () => {
const [firstQuery, setFirstQuery] = useState('');
const _onChange = query => setFirstQuery(query);
return (
<Searchbar
style={{marginTop: 60}}
placeholder="Search"
onChangeText={_onChange}
value={firstQuery}
/>
);
}
const MyComponent = () => {
const [firstQuery, setFirstQuery] = useState('');
const handleChange = (query) => setFirstQuery(query);
return (
<Searchbar
style={{marginTop: 60}}
placeholder="Search"
onChangeText={handleChange}
value={firstQuery}
/>
);
}
Try this way
import * as React from 'react';
import { Searchbar } from 'react-native-paper';
const MyComponent = (props) => {
const [firstQuery, setFirstQuery] = React.useState('');
return (
<Searchbar
style={{marginTop: 60}}
placeholder="Search"
onChangeText={query => { setFirstQuery(query) }}
value={firstQuery}
/>
);
}
export default MyComponent;
This should do it for you:
//Only get what we need to reduce overhead
import React, { useState } from "react";
import { Searchbar } from "react-native-paper";
//you may include props here if needed, otherwise = () =>
const MyComponent = (props) => {
//State as hook, first object in array will be value second will be function to set value and notify update required
const [firstQuery, setFirstQuery] = useState("");
//handle for onChangeText
const onChangeTextHandle = (query) => {
//set state using hook
setFirstQuery(query);
};
//No need for render method, just return JSX
return (
<Searchbar
style={{ marginTop: 60 }}
placeholder="Search"
onChangeText={onChangeTextHandle}
value={firstQuery}
/>
);
};
//Export component Here
export default MyComponent;

Resources