Error: Cannot call useFirebaseApp unless your component is within a FirebaseAppProvider - reactjs

I get this error when i go createNewPost page, I do not know why, could you help me please ? What is the problem?
The other pages (homepage and profile page) does not any problem.
(I researched, but i couldn't find anything.)
Error: Cannot call useFirebaseApp unless your component is within a FirebaseAppProvider
my createNewPost page codes here:
const CreateNewPost = () => {
const { user } = useAuth();
const uid = firebase.auth().currentUser.uid;
const postRef = useFirestore()
.collection("users")
.doc(uid)
.collection("posts");
const [post, setPost] = useState({
content: "",
imageURL: "",
});
const createPost = async () => {
await postRef.add({
content: post.content,
imageURL: post.imageURL,
timezone: dateFormat(),
});
setPost({ content: "", imageURL: "" });
};
return (
<>
<div className="container">
<form>
<div class="form-group">
<div className="d-flex justify-content-start ">
<div className="d-flex align-items-center">
<img
className="rounded-circle py-2"
alt="profile"
src={user.photoURL}
style={{
maxHeight: "80px",
maxWidth: "80px",
marginBottom: "-17px",
}}
/>
<h2 style={{ marginLeft: "7px", marginTop: "16px" }}>
{user.displayName}
</h2>
</div>
</div>
<hr></hr>
<textarea
class="form-control"
id="exampleFormControlTextarea1"
rows="23"
placeholder="Enter a description..."
onChange={(e) => setPost({ content: e.target.value })}
></textarea>
</div>
</form>
<input
class="form-control"
type="text"
placeholder="Enter the image link"
style={{ marginTop: "7px" }}
onChange={(e) => setPost({ imageURL: e.target.value })}
></input>
<div className="d-flex justify-content-end">
<button
type="button"
class="btn btn-primary btn-lg"
style={{ marginTop: "3px" }}
onClick={createPost}
>
Post
</button>
</div>
</div>
</>
);
};

I used Firebase app provider in index.jsx like this, and i solved:
ReactDOM.render(
<FirebaseAppProvider firebaseConfig={firebaseConfig}>
<App />
</FirebaseAppProvider>
,
document.getElementById('root')
);

Related

Why my state is not changing to false and true?

I want to set Iscandidate to true if user role === "candidate" and same for comapny if userrole === "company" and other should be false . I am saving isCandidate and isCompany as true and false in DB , if one is true the other should be false but I am not getting desired output.
What I am trying is :
console.log("signin card");
const [phoneNumber, setPhoneNumber] = useState("");
const [isCompany, setIsCompany] = useState(null);
const [isCandidate, setIsCandidate] = useState(null);
const body = {
phoneNumber,
isCandidate,
isCompany,
};
const onSubmitHandler = async () => {
if (userRole === "candidate") {
console.log(userRole);
setIsCandidate(true);
setIsCompany(false);
}
if (userRole === "company") {
console.log(userRole);
setIsCandidate(false);
setIsCompany(true);
}
console.log("body : ", body);
const res = await axios.post(
"http://localhost:8000/user-role/recorded",
body
);
const otpRes = await axios.get(
`https://2factor.in/API/V1/b3014f3e-2e06-11ea-9fa5-0200cd936042/SMS/+91${phoneNumber}/AUTOGEN3`
);
console.log("res = ", res);
console.log("otp = ", otpRes);
};
const onChangeHandler = (e) => {
setPhoneNumber(e.target.value);
};
return (
<>
<div
className="modal"
id="signInCard"
tabIndex="-1"
aria-hidden="true"
style={{
position: "fixed",
top: "0%",
left: "50%",
width: "100%",
height: "100%",
overflowX: "hidden",
overflowY: "auto",
transform: "translateX(-50%)",
zIndex: "1055",
}}
>
<div
className="modal-dialog modal-dialog-centered"
style={{ width: "20%" }}
>
<div className="modal-content">
<div className="modal-body p-5">
<div className="position-absolute end-0 top-0 p-3">
<button
type="button"
className="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div className="auth-content">
<div className="w-100">
<div className="text-center mb-4">
<h5>Sign In as {userRole}</h5>
<p className="text-muted"></p>
</div>
<form
onSubmit={(e) => {
onSubmitHandler();
}}
className="auth-form"
>
<div className="input-group mb-3">
{/* <label for="usernameInput" className="form-label">Phone No.</label> */}
<div className="input-group-prepend">
<span className="input-group-text" id="basic-addon1">
+91
</span>
</div>
<input
type="number"
name="phoneNumber"
className="form-control"
id="usernameInput"
placeholder="Enter your phone no."
aria-label="number"
aria-describedby="basic-addon1"
onChange={onChangeHandler}
value={phoneNumber}
/>
<span className="text-danger"></span>
</div>
<div className="text-center">
<a href="#otpModal" data-bs-toggle="modal">
<button
type="submit"
className="btn btn-primary w-100"
onClick={onSubmitHandler}
>
Sign In
</button>
</a>
{/* <a
href="#otpModal"
className="form-text user_sign"
data-bs-toggle="modal"
>
Candidate
</a> */}
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
Please help while saving into Db I am getting null
You're posting the data into db just after setting the state. You have to change that
let body = {
phoneNumber,
isCandidate,
isCompany,
};
const onSubmitHandler = async () => {
if (userRole === "candidate") {
console.log(userRole);
setIsCandidate(true);
setIsCompany(false);
body.isCandidate = true;
body.isCompany = false
}
if (userRole === "company") {
console.log(userRole);
setIsCandidate(false);
setIsCompany(true);
body.isCandidate = false;
body.isCompany = true
}
console.log("body : ", body);
const res = await axios.post(
"http://localhost:8000/user-role/recorded",
body
);
const otpRes = await axios.get(
`https://2factor.in/API/V1/b3014f3e-2e06-11ea-9fa5-0200cd936042/SMS/+91${phoneNumber}/AUTOGEN3`
);
console.log("res = ", res);
console.log("otp = ", otpRes);
};
.
You could do something like this:
Instead of using isCompany and isCandidate as states(because they aren't referred to anywhere in the component), update body inside the onSubmitHandler function itself.
console.log("signin card");
const [phoneNumber, setPhoneNumber] = useState("");
const onSubmitHandler = async () => {
const body = {
phoneNumber
};
console.log(userRole);
if (userRole === "candidate") {
body.isCandidate = true;
body.isCompany = false;
}
else if (userRole === "company") {
body.isCandidate = false;
body.isCompany = true;
}
console.log("body : ", body);
const res = await axios.post(
"http://localhost:8000/user-role/recorded",
body
);
const otpRes = await axios.get(
`https://2factor.in/API/V1/b3014f3e-2e06-11ea-9fa5-0200cd936042/SMS/+91${phoneNumber}/AUTOGEN3`
);
console.log("res = ", res);
console.log("otp = ", otpRes);
};
const onChangeHandler = (e) => {
setPhoneNumber(e.target.value);
};
return (
<>
<div
className="modal"
id="signInCard"
tabIndex="-1"
aria-hidden="true"
style={{
position: "fixed",
top: "0%",
left: "50%",
width: "100%",
height: "100%",
overflowX: "hidden",
overflowY: "auto",
transform: "translateX(-50%)",
zIndex: "1055",
}}
>
<div
className="modal-dialog modal-dialog-centered"
style={{ width: "20%" }}
>
<div className="modal-content">
<div className="modal-body p-5">
<div className="position-absolute end-0 top-0 p-3">
<button
type="button"
className="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div className="auth-content">
<div className="w-100">
<div className="text-center mb-4">
<h5>Sign In as {userRole}</h5>
<p className="text-muted"></p>
</div>
<form
onSubmit={(e) => {
onSubmitHandler();
}}
className="auth-form"
>
<div className="input-group mb-3">
{/* <label for="usernameInput" className="form-label">Phone No.</label> */}
<div className="input-group-prepend">
<span className="input-group-text" id="basic-addon1">
+91
</span>
</div>
<input
type="number"
name="phoneNumber"
className="form-control"
id="usernameInput"
placeholder="Enter your phone no."
aria-label="number"
aria-describedby="basic-addon1"
onChange={onChangeHandler}
value={phoneNumber}
/>
<span className="text-danger"></span>
</div>
<div className="text-center">
<a href="#otpModal" data-bs-toggle="modal">
<button
type="submit"
className="btn btn-primary w-100"
onClick={onSubmitHandler}
>
Sign In
</button>
</a>
{/* <a
href="#otpModal"
className="form-text user_sign"
data-bs-toggle="modal"
>
Candidate
</a> */}
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>

Using working fileupload code inside a form with formki api

I have my form using formik. and I want to use the file upload logic in my form which is shown in the sandbox here.
Quick Description of what's in sandbox:
User uploads a file, and based on the # of files, they will see a datatable rows and answer some questions by editing that row using edit button and then saving their response using checkmark button.
Right now, when a user hits Save button, it prints in the console log the values of what user has selected as an array of object.
I don't want to have this additional Save button in my form and want to send these values when a user hits the Submit button of my form along with other values.
I was playing with my sandbox code by putting it at the location in my form where {uploadDocumentSection} is mentioned in my code below. However,
I'm unable to get the data from the dynamicData variable which is storing the responses from the user.
Is it possible to achieve what I'm looking for?
return (
<div>
<style jsx>{`
text-align: center;
padding: 5px;
#formEdwDiv {
padding: 20px;
}
`}
</style>
<div id="formEdwDiv">
<Growl ref={growl}/>
<Form className="form-column-3">
<div className="datarequest-form">
<div className="form-field field-full-width">
<label className="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-animated custom-label">Title <span className="astrick">*</span></label>
<CustomTextField name="title" type="text"/>
</div>
<div className="form-field field-full-width">
<label className="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-animated custom-label">Description <span className="astrick">*</span></label>
<CustomTextAreaField name = "description" type ="text" />
{touched.description && errors.description && <Message severity="error" text={errors.description}/>}
</div>
</div>
{uploadDocumentSection}
<div className="btn-group-right">
<Button size="large" variant="contained" color="primary" id="edw-submit"
type="submit">Submit</Button>
<Button size="large" variant="contained" color="primary" onClick={handleReset}
style={{marginLeft: '5px'}} type="button">Reset</Button>
<Button size="large" variant="contained" color="primary" onClick={props.onCancel}
style={{marginLeft: '5px'}} type="button">Cancel</Button>
</div>
</Form>
</div>
</div>
)
};
export const RequestEnhancedForm = withFormik(
{
mapPropsToValues: props => {
return {
requestId: props.dataRequest && props.dataRequest.requestId || '',
title: props.dataRequest && props.dataRequest.title || '',
}
},
validationSchema:validationSchema,
handleSubmit(values, {props, resetForm, setErrors, setSubmitting}) {
console.log("submit data request form....")
props.handleSubmit(values)
setSubmitting(false)
},
setFieldValue(field, value, shouldVal) {
console.log('In setFieldValue')
},
displayName: 'Data Request Form',
})(DataRequestForm)
Here is my code from Codesandbox if needed:
const answers = [
{ label: "Yes", value: "YES" },
{ label: "No", value: "NO" }
];
export const FileUploadDemo = () => {
const toast = useRef(null);
const fileUploadRef = useRef(null);
const [dynamicData, setDynamicData] = useState([]);
const getAnswerLabel = (answer) => {
switch (answer) {
case "YES":
return "Yes";
case "NO":
return "No";
default:
return "NA";
}
};
const onRowEditComplete1 = (e) => {
console.log("Testing e");
console.log(e);
let _dynamicData = [...dynamicData];
let { newData, index } = e;
_dynamicData[index] = newData;
setDynamicData(_dynamicData);
};
const textEditor = (options) => {
return (
<InputText
type="text"
value={options.value}
onChange={(e) => options.editorCallback(e.target.value)}
/>
);
};
const answerEditor = (options) => {
return (
<Dropdown
value={options.value}
options={answers}
optionLabel="label"
optionValue="value"
onChange={(e) => options.editorCallback(e.value)}
placeholder="Select an answer"
itemTemplate={(option) => {
return <span className={`product-badge`}>{option.label}</span>;
}}
/>
);
};
const answer1BodyTemplate = (rowData) => {
return getAnswerLabel(rowData.answer1);
};
const answer2BodyTemplate = (rowData) => {
return getAnswerLabel(rowData.answer2);
};
const onUpload = (e) => {
// toast.current.show({
// severity: "info",
// summary: "Success",
// detail: "File Uploaded"
// });
console.log("File Upload event e");
console.log(e);
const newData = e.files.map((file) => ({
filename: file.name,
answer1: null,
answer2: null,
description: ""
}));
setDynamicData([...dynamicData, ...newData]);
};
return (
<div>
<Tooltip target=".custom-choose-btn" content="Choose" position="bottom" />
<Tooltip target=".custom-upload-btn" content="Upload" position="bottom" />
<Tooltip target=".custom-cancel-btn" content="Clear" position="bottom" />
<div className="card">
<h5>Advanced</h5>
<FileUpload
name="demo[]"
url="https://primefaces.org/primereact/showcase/upload.php"
onUpload={onUpload}
customUpload
uploadHandler={onUpload}
multiple
accept="image/*"
maxFileSize={1000000}
emptyTemplate={
<p className="m-0">Drag and drop files to here to upload.</p>
}
/>
</div>
<div className="datatable-editing-demo">
{/* <Toast ref={toast} /> */}
<div className="card p-fluid">
<h5>Row Editing</h5>
<DataTable
value={dynamicData}
editMode="row"
dataKey="id"
onRowEditComplete={onRowEditComplete1}
responsiveLayout="scroll"
>
<Column
field="filename"
header="Filename"
editor={(options) => textEditor(options)}
style={{ width: "20%" }}
></Column>
<Column
field="answer1"
header="Q1"
body={answer1BodyTemplate}
editor={(options) => answerEditor(options)}
style={{ width: "20%" }}
></Column>
<Column
field="answer2"
header="Q2"
body={answer2BodyTemplate}
editor={(options) => answerEditor(options)}
style={{ width: "20%" }}
></Column>
<Column
field="description"
header="Description"
editor={(options) => textEditor(options)}
style={{ width: "20%" }}
></Column>
<Column
rowEditor
headerStyle={{ width: "10%", minWidth: "8rem" }}
bodyStyle={{ textAlign: "center" }}
></Column>
</DataTable>
</div>
</div>
<Button label="Save" onClick={() => console.log(dynamicData)} />
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<FileUploadDemo />, rootElement);

I am new to react and when i click on submit button nothing happens?

Here is the code!!
Actually very new to react and i am working on a project which is about to-do list but while doing this i am stuck on rendering the output of the input field in the list item. if there is another solution like without the list group it would be very helpful!
Where i am doing the actual mistake please someone look upon this
Thanks in advance!
import React, { Component, Fragment } from "react";
class MainPage extends Component {
state = { data: "" };
handleChange = (e) => {
e.preventDefault();};
handleSubmit = (e) => {
e.preventDefault();
this.setState({ data: e.target.value });
};
render() {
const mystyle = {
padding: "16px 16px 16px 60px",
textAlign: "start",
fontSize: "24px",
fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif',
width: "500px",
};
return (
<Fragment>
<h1 className="display-1 text-center" style={{ color: "#f7c6c6" }}>
todos
</h1>
<form className="todo-form" onSubmit={this.handleSubmit}>
<input
type="text"
onChange={this.handleChange.bind(this)}
className="new-todo shadow-lg p-3 mb-5 bg-white rounded"
style={mystyle}
placeholder="What needs to be done?"
/>
<button className="btn btn-primary btn-sm ml-3">Submit</button>
<ul className="list-group">
<li
className="list-group-item disabled p-3 mb-5 w-50 p-3 mx-auto "
style={{ width: "200px", fontSize: "24px" }}
>
{this.state.data}
</li>
</ul>
</form>
</Fragment>
);}}
export default MainPage;
There are some issues in your code:
You want to submit on button. For that you need to add type="submit"
<button className="btn btn-primary btn-sm ml-3" type="submit">
Submit
</button>
You need to maintain two states first for input and second for todo's. In that way you can always append in existing todo when user submits form:
state = { data: [], input: "" };
Last you are saving value onSubmit but it has not e.target.value instead you need to save in onHandleChage
Here is full code:
import React, { Component, Fragment } from "react";
class MainPage extends Component {
state = { data: [], input: "" };
handleChange = (e) => {
e.preventDefault();
this.setState({ input: e.target.value });
};
handleSubmit = (e) => {
e.preventDefault();
this.setState({ data: [...this.state.data, this.state.input], input: "" });
};
render() {
const mystyle = {
padding: "16px 16px 16px 60px",
textAlign: "start",
fontSize: "24px",
fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif',
width: "500px"
};
return (
<Fragment>
<h1 className="display-1 text-center" style={{ color: "#f7c6c6" }}>
todos
</h1>
<form className="todo-form" onSubmit={this.handleSubmit}>
<input
type="text"
onChange={this.handleChange.bind(this)}
value={this.state.input}
className="new-todo shadow-lg p-3 mb-5 bg-white rounded"
style={mystyle}
placeholder="What needs to be done?"
/>
<button className="btn btn-primary btn-sm ml-3" type="submit">
Submit
</button>
<ul className="list-group">
{this.state.data.map((data, i) => {
return (
<li
className="list-group-item disabled p-3 mb-5 w-50 p-3 mx-auto "
style={{ width: "200px", fontSize: "24px" }}
key={"todo-" + i}
>
{data}
</li>
);
})}
</ul>
</form>
</Fragment>
);
}
}
export default function App() {
return (
<div className="App">
<MainPage />
</div>
);
}
Here is the demo: https://codesandbox.io/s/xenodochial-banzai-qwxfu?file=/src/App.js:0-1762
import React, { Component, Fragment } from "react";
class MainPage extends Component {
state = { data: "" };
handleSubmit = (e) => {
e.preventDefault();
alert(data)
};
render() {
const mystyle = {
padding: "16px 16px 16px 60px",
textAlign: "start",
fontSize: "24px",
fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif',
width: "500px",
};
return (
<Fragment>
<h1 className="display-1 text-center" style={{ color: "#f7c6c6" }}>
todos
</h1>
<form className="todo-form" onSubmit={this.handleSubmit}>
<input
type="text"
onChange={(e) => this.setState({data: e.target.value})}
className="new-todo shadow-lg p-3 mb-5 bg-white rounded"
style={mystyle}
placeholder="What needs to be done?"
/>
<button className="btn btn-primary btn-sm ml-3">Submit</button>
<ul className="list-group">
<li
className="list-group-item disabled p-3 mb-5 w-50 p-3 mx-auto "
style={{ width: "200px", fontSize: "24px" }}
>
{this.state.data}
</li>
</ul>
</form>
</Fragment>
);}}
Try it like:
state = { data: "", FinalDataValue:"" };
handleChange = (e) => {
e.preventDefault();
this.setState({ data: e.target.value });};
handleSubmit = (e) => {
e.preventDefault();
this.setState({ FinalDataValue:this.state.data });};
and in render in list write it like :
<li
className="list-group-item disabled p-3 mb-5 w-50 p-3 mx-auto "
style={{ width: "200px", fontSize: "24px" }}
>
{this.state.FinalDataValue}
</li>

Update the input value from one component in an other on runtime

I have a NotificationStepper Component which gets inputs from user, I need to update this input value in run time in another component named TabComponent. Both of the components are child components of SendNotification Component. How can i achieve that in reactjs.
EDIT
NotificationStepper.js
const styles = {
transparentBar: {
backgroundColor: 'transparent !important',
boxShadow: 'none',
paddingTop: '25px',
color: '#FFFFFF'
}
};
const useStyles = makeStyles((theme: Theme) =>
createStyles({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}),
);
function getSteps() {
return ['Create', 'Audience', 'Timing'];
}
function getStepContent(step, $this) {
switch (step) {
case 0:
return (
<div className="row">
<CardBox styleName="col-lg-12"
heading="">
<form className="row" noValidate autoComplete="off" style={{"flex-wrap":"no-wrap", "flex-direction": "column" }}>
<div className="col-md-12 col-12">
<TextField
id="campaign_name"
label="Campaign Name"
value={$this.state.name}
onChange={$this.handleChange('name')}
margin="normal"
fullWidth
/>
</div>
</form>
</CardBox>
</div>
);
default:
return 'Unknown step';
}
}
class NotificationStepper extends React.Component {
state = {
activeStep: 0,
name: '',
};
handleChange = name => event => {
this.setState({
[name]: event.target.value,
});
};
handleNext = () => {
this.setState({
activeStep: this.state.activeStep + 1,
});
};
handleBack = () => {
this.setState({
activeStep: this.state.activeStep - 1,
});
};
handleReset = () => {
this.setState({
activeStep: 0,
});
};
render() {
const steps = getSteps();
const {activeStep} = this.state;
return (
<div className="col-xl-12 col-lg-12 col-md-7 col-12">
<Stepper className="MuiPaper-root-custom" activeStep={activeStep} orientation="vertical">
{steps.map((label, index) => {
return (
<Step key={label}>
<StepLabel>{label}</StepLabel>
<StepContent className="pb-3">
<Typography>{getStepContent(index, this)}</Typography>
<div className="mt-2">
<div>
<Button
disabled={activeStep === 0}
onClick={this.handleBack}
className="jr-btn"
>
Back
</Button>
<Button
variant="contained"
color="primary"
onClick={this.handleNext}
className="jr-btn"
>
{activeStep === steps.length - 1 ? 'Finish' : 'Next'}
</Button>
</div>
</div>
</StepContent>
</Step>
);
})}
</Stepper>
{activeStep === steps.length && (
<Paper square elevation={0} className="p-2">
<Typography>All steps completed - you"re finished</Typography>
<Button onClick={this.handleReset} className="jr-btn">
Reset
</Button>
</Paper>
)}
</div>
);
}
}
export default NotificationStepper;
TabComponent.js
TabContainer.propTypes = {
children: PropTypes.node.isRequired,
dir: PropTypes.string.isRequired,
};
class TabComponent extends Component {
state = {
value: 0,
};
render() {
const {theme} = this.props;
return (
<div className="col-xl-12 col-lg-12 col-md-12 col-12" style={{"margin-top": "15px"}}>
<NotifCard key={0} data={{'name': 'Title of Notification', 'company': 'sayge.ai', 'image': require("assets/images/chrome.png"), 'description': 'Notification Message here'}} styleName="card shadow "/>
</div>
);
}
}
TabComponent.propTypes = {
theme: PropTypes.object.isRequired,
};
export default withStyles(null, {withTheme: true})(TabComponent);
and this is my SendNotification.js
const SendNotification = ({match}) => {
return (
<div className="dashboard animated slideInUpTiny animation-duration-3">
<ContainerHeader match={match} title={<IntlMessages id="sidebar.notification"/>}/>
<div className="row" style={{'flex-wrap': 'no wrap', "flex-direction": 'row'}}>
<div className="col-xl-7 col-lg-7 col-md-7 col-7">
<NotificationStepper/>
<div className='flex-class' style={{'width': '100%'}}>
<Button color="primary" style={{"align-self": "flex-end", "border" : "1px solid", "margin-left": "10px", "margin-bottom": "40px"}} size="small" className="col-md-2 col-2">Fetch</Button>
<Button color="primary" style={{"align-self": "flex-end", "border" : "1px solid", "margin-left": "10px", "margin-bottom": "40px"}} size="small" className="col-md-2 col-2" color="primary">Discard</Button>
</div>
</div>
<div className="col-xl-5 col-lg-5 col-md-5 col-5" style={{"padding-top": "20px"}}>
<span style={{"margin-left" : "20px", "font-weight": "bold"}}>Preview</span>
<TabComponent />
</div>
</div>
</div>
);
};
export default SendNotification;
i need to get the name value from NotificationStepper and Update it in pass it to in TabComponent.
There are plenty of tutorials about that. For instance, this.
import React, { Component, createRef } from "react";
class CustomTextInput extends Component {
textInput = createRef();
focusTextInput = () => this.textInput.current.focus();
render() {
return (
<>
<input type="text" ref={this.textInput} />
<button onClick={this.focusTextInput}>Focus the text input</button>
</>
);
}
}
import React, { useRef } from "react";
const CustomTextInput = () => {
const textInput = useRef();
focusTextInput = () => textInput.current.focus();
return (
<>
<input type="text" ref={textInput} />
<button onClick={focusTextInput}>Focus the text input</button>
</>
);
}

Pass props to child component from parent component dynamically

I have a child component StepperNotification which gets an input from user and returns it as prop to its child component in following way.
const styles = {
transparentBar: {
backgroundColor: 'transparent !important',
boxShadow: 'none',
paddingTop: '25px',
color: '#FFFFFF'
}
};
const useStyles = makeStyles((theme: Theme) =>
createStyles({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}),
);
function getSteps() {
return ['Create', 'Audience', 'Timing'];
}
function getStepContent(step, $this) {
switch (step) {
case 0:
return (
<div className="row">
<CardBox styleName="col-lg-12"
heading="">
<form className="row" noValidate autoComplete="off" style={{"flex-wrap":"no-wrap", "flex-direction": "column" }}>
<div className="col-md-12 col-12">
<TextField
id="campaign_name"
label="Campaign Name"
value={$this.state.name}
onChange={$this.handleChange('name')}
margin="normal"
fullWidth
/>
</div>
</form>
</CardBox>
</div>
);
default:
return 'Unknown step';
}
}
class NotificationStepper extends React.Component {
state = {
activeStep: 0,
name: '',
};
handleChange = name => event => {
this.setState({
[name]: event.target.value,
});
this.props.titlechange(event.target.value);
};
handleNext = () => {
this.setState({
activeStep: this.state.activeStep + 1,
});
};
handleBack = () => {
this.setState({
activeStep: this.state.activeStep - 1,
});
};
handleReset = () => {
this.setState({
activeStep: 0,
});
};
render() {
const steps = getSteps();
const {activeStep} = this.state;
return (
<div className="col-xl-12 col-lg-12 col-md-7 col-12">
<Stepper className="MuiPaper-root-custom" activeStep={activeStep} orientation="vertical">
{steps.map((label, index) => {
return (
<Step key={label}>
<StepLabel>{label}</StepLabel>
<StepContent className="pb-3">
<Typography>{getStepContent(index, this)}</Typography>
<div className="mt-2">
<div>
<Button
disabled={activeStep === 0}
onClick={this.handleBack}
className="jr-btn"
>
Back
</Button>
<Button
variant="contained"
color="primary"
onClick={this.handleNext}
className="jr-btn"
>
{activeStep === steps.length - 1 ? 'Finish' : 'Next'}
</Button>
</div>
</div>
</StepContent>
</Step>
);
})}
</Stepper>
{activeStep === steps.length && (
<Paper square elevation={0} className="p-2">
<Typography>All steps completed - you"re finished</Typography>
<Button onClick={this.handleReset} className="jr-btn">
Reset
</Button>
</Paper>
)}
</div>
);
}
}
export default NotificationStepper;
In my parent component i am getting this prop value and passing it to another child component Tabcomponent in following way
ParentCompoennt.js
const SendNotification = ({match}) => {
let titlename = '';
let message = '';
function handleTitle(title_) {
console.log('in here');
console.log(title_);
titlename = title_;
}
return (
<div className="dashboard animated slideInUpTiny animation-duration-3">
<ContainerHeader match={match} title={<IntlMessages id="sidebar.notification"/>}/>
<div className="row" style={{'flex-wrap': 'no wrap', "flex-direction": 'row'}}>
<div className="col-xl-7 col-lg-7 col-md-7 col-7">
<NotificationStepper titlechange={handleTitle} />
<div className='flex-class' style={{'width': '100%'}}>
<Button color="primary" style={{"align-self": "flex-end", "border" : "1px solid", "margin-left": "10px", "margin-bottom": "40px"}} size="small" className="col-md-2 col-2">Fetch</Button>
<Button color="primary" style={{"align-self": "flex-end", "border" : "1px solid", "margin-left": "10px", "margin-bottom": "40px"}} size="small" className="col-md-2 col-2" color="primary">Discard</Button>
</div>
</div>
<div className="col-xl-5 col-lg-5 col-md-5 col-5" style={{"padding-top": "20px"}}>
<span style={{"margin-left" : "20px", "font-weight": "bold"}}>Preview</span>
<TabComponent {...{[title]:titlename}} message={message} />
</div>
</div>
</div>
);
};
export default SendNotification;
and in TabComponent i am getting this prop value and using it component in following way
TabContainer.propTypes = {
children: PropTypes.node.isRequired,
dir: PropTypes.string.isRequired,
};
class TabComponent extends Component {
state = {
value: 0,
};
render() {
const {theme} = this.props;
const title = this.props.title;
return (
<div className="col-xl-12 col-lg-12 col-md-12 col-12" style={{"margin-top": "15px"}}>
<NotifCard key={0} data={{'name': title, 'company': 'sayge.ai', 'image': require("assets/images/bell.png"), 'description': this.props.message}} styleName="card shadow "/>
</div>
);
}
}
TabComponent.propTypes = {
theme: PropTypes.object.isRequired,
};
export default withStyles(null, {withTheme: true})(TabComponent);
StepperNotification is working fine and props are being updated in parent. i have checked this by printing the updated values in console, but the props in TabComponent are not being updated. What am i doing wrong here? any help is appreciated.
Probaly this is your issue
<TabComponent {...{[title]:titlename}} message={message} />` this could be just
title is undefined and you are sending props[undefined]=titlename
Just do this
<TabComponent title={titlename} message={message} />`
And if SendNotification is react fuction component useState for keeping track of current titlename. If it still doesn't work after first fix this second will be another source of your problems.

Resources