Reputation: 787
I have a root component as:
const EnterMobileNumberPage: React.FC = () => {
return (
<div
className="Page"
id="enterMobileNumberPage"
>
<CardView>
<p
className="TitleLabel"
>
Please enter your mobile number
</p>
<input
className="PlainInput"
type="text"
maxLength={10}
onChange={inputAction}
/>
<FilledButton
title="Next"
action={buttonAction}
invalid
/>
</CardView>
</div>
);
}
Where CardView
and FilledButton
are my custom components. FilledButton
has logic shown below:
type FilledButtonProps = {
title: string,
bgcolor?: string,
color?: string,
invalid?: boolean,
action?: ()=>void
}
const FilledButton: React.FC<FilledButtonProps> = (props) => {
const [, updateState] = React.useState();
const forceUpdate = React.useCallback(() => updateState({}), []);
let backgroundColor: string | undefined
if(props.bgcolor){
backgroundColor = props.bgcolor
}
if(props.invalid === true){
backgroundColor = "#bcbcbc"
}
const overrideStyle: CSS.Properties = {
backgroundColor: backgroundColor,
color: props.color
}
return (
<a
className="FilledButton"
onClick={props.action}
>
<div style={overrideStyle}>
{props.title}
</div>
</a>
);
}
Here, I want to listen to text change event in input element. What should I write so that inputAction
has a way to update FilledButton
?
For example, I may want to change FilledButton
's invalid
to false
when input element has 10 digits number.
(I didn't introduce Redux, since I'm quite a beginner)
Upvotes: 1
Views: 2188
Reputation: 2922
so if you want to update the props receibe by <FilledButton />
, you only need to store a state (call it action
, maybe) when your inputAction
onChange function is trigger, that way you'll update that state and that state is been pass to you children component:
import React, { useState } from 'react';
const EnterMobileNumberPage: React.FC = () => {
const [action, setAction] = React.useState('');
const handleChange = e => {
if (e && e.target && e.target.value) {
setAction(e.target.value);
}
};
return (
<div
className="Page"
id="enterMobileNumberPage"
>
<CardView>
<p className="TitleLabel" >
Please enter your mobile number
</p>
<input
className="PlainInput"
type="text"
maxLength={10}
onChange={handleChange}
/>
<FilledButton
title="Next"
action={buttonAction}
invalid={action.length === 10}
/>
</CardView>
</div>
);
}
Then, you'll have an action
estate, that you could use to block your <FilledButton />
and also to use it as the <input />
value, Hope this helps.
Upvotes: 1
Reputation: 4330
Since you want to update sibling component, the only way you have is to re-render parent component and pass updated prop to sibling component so it will also update.
const EnterMobileNumberPage: React.FC = () => {
const [mobileVal, inputAction] = React.useState('');
return (
<div>
<input
className="PlainInput"
type="text"
maxLength={10}
onChange={inputAction} // Updating parent component state on change
/>
<FilledButton
title="Next"
action={buttonAction}
invalid
mobileLength={mobileVal.length} // New prop for filled button
/>
</div>
);
}
Upvotes: 1