reactjs


Wrapping a TextField in my own reusable component


So I have a component that adds a * at the beginning of typed in text that looks like this:
export default class MyTextField extends Component {
constructor() {
super();
this.state = {
value: '',
};
}
static propTypes = {
onChange: PropTypes.func,
value: PropTypes.string
}
addSymbol(newValue, symbol) {
return newValue.indexOf(symbol) === -1 ? `${symbol}${newValue}` : newValue;
}
change(input, newValue) {
console.log(`I am the parent wit newValue ${newValue}.`);
this.setState({
value: this.addSymbol(newValue, '*')
});
}
render() {
const {
onChange, // eslint-disable-line no-unused-vars
...other
} = this.props;
return (
<TextField
value={this.state.value}
onChange={this.change.bind(this)}
{...other } >
</TextField >
);
}
}
Now I use MyTextFieldin another component like this:
<MyTextField
style={styleTextFields}
floatingLabelText='Add text'
type='text'
/>
Now when I start typing everything works great.
If I change the code above and add value='test' prop on MyTextField everything breaks. It appears its because I added a prop to TextField which can not be overwritten by MyTextField value={this.state.value}.
So how can I add prop value and still add a * at the beginning of the typed text?
The other part is if the user adds their own onChange, how can I get both MyTextField and the component using MyTextField onChange events to get called?
=======Beginning of Edit 1===============
#Patrick - I have made tweaks based on your comment and the first part is now working. So I can type in <TextField /> and I see the changes.
The changes are below:
export default class MyTextField extends Component {
constructor(props) {
super();
this.state = {
value: props.value ? this.addSymbol(props.value.toString(), '*') : ''
};
}
static propTypes = {
onChange: PropTypes.func,
value: PropTypes.string
}
addSymbol(newValue, symbol) {
return newValue.indexOf(symbol) === -1 ? `${symbol}${newValue}` : newValue;
}
change(input, newValue) {
console.log(`I am the parent wit newValue ${newValue}.`);
this.setState({
value: this.addSymbol(newValue, '*')
});
}
render() {
const {
value, // eslint-disable-line no-unused-vars
onChange, // eslint-disable-line no-unused-vars
...other
} = this.props;
return (
<TextField
value={this.state.value}
onChange={this.change.bind(this)}
{...other } >
</TextField >
);
}
}
I am not sure how to make the onChange tweak because you are not supposed to modify component state?
I also did try this in the render() function which does not work:
addSymbol(newValue, symbol) {
return newValue.indexOf(symbol) === -1 ? `${symbol}${newValue}` : newValue;
}
change(input, newValue) {
console.log(`I am the parent wit newValue ${newValue}.`);
this.setState({
value: this.addSymbol(newValue, '*')
});
}
render() {
const {
value, // eslint-disable-line no-unused-vars
onChange, // eslint-disable-line no-unused-vars
...other
} = this.props;
return (
<TextField
value={this.addSymbol(this.state.value, '*')}
{...other } >
</TextField >
);
}
Anyway, thank you for your help.
=======Ending of Edit 1===============
=======Beginning of Edit 2===============
I fixed the onChange event problem by adding my own event called onNewValueChange and calling it in the onChange. Here is the final code:
export default class MyTextField extends Component {
constructor() {
super();
this.state = {
value: props.value ? this.addSymbol(props.value.toString(), '*') : ''
};
}
static propTypes = {
onNewValueChange: PropTypes.func,
value: PropTypes.string
}
addSymbol(newValue, symbol) {
return newValue.indexOf(symbol) === -1 ? `${symbol}${newValue}` : newValue;
}
change(input, newValue) {
const value = value: props.value ? this.addSymbol(props.value.toString(), '*') : '';
this.setState({
value: value
});
if(this.props.onNewValueChange) {
this.props.onNewValueChange(value);
}
}
render() {
const {
onNewValueChange, // eslint-disable-line no-unused-vars
...other
} = this.props;
return (
<TextField
value={this.state.value}
onChange={this.change.bind(this)}
{...other } >
</TextField >
);
}
}
Now I use MyTextField in another component like this:
<MyTextField
style={styleTextFields}
floatingLabelText='Add text'
type='text'
onNewValueChange={(newValue) => console.log(newValue) }
/>
#Patrick thank you for your help getting me in the right direction.
=======Ending of Edit 2===============
In general, I think this pattern of omitting props before passing everything else inside a component is confusing, at least for me. Being explicit as possible should always be a priority.
If I understood you correctly, the expected behavior is as follows:
You can pass a default text, this text should be prefixed with a * by your component.
You can modify the text, but no matter how you modify it, it should always be prefixed with a * - so an empty string should just be *.
I've created this fiddle which hopefully does what you meant : https://jsfiddle.net/69z2wepo/78041/
The key concept is to separate between props and state, a prop is passed only once, and should really be responsible for the initial state of your
Here's the two classes I created :
class Input extends React.Component{
render(){
return (<input onChange={this.props.onChange} value={this.props.value}/>)
}
}
class WrappedInput extends React.Component{
constructor(props){
super();
let val = props.value || '';
this.state = {
value : this.addSymbol(val,'*')
}
}
handleChange(e){
let newVal = e.target.value;
this.setState({value:this.addSymbol(newVal,'*')});
}
addSymbol(newValue, symbol) {
return newValue.indexOf(symbol) === -1 ? `${symbol}${newValue}` : newValue;
}
render(){
return (<Input onChange={this.handleChange.bind(this)} value={this.state.value}/>)
}
}

Related Links

ReactJS component not rerendering when props are passed
React Redux … syntax error
How does one set the tabIndex attribute on a draft-js instance?
ComponentDidMount() not working
UIScrollView Canvas Equivalent?
ReactJS - props or propTypes?
React Router V4 structure
Should a view be ordering data?
Unable to load React class component inside other class component
How to get history on react-router v4?
Redux react immutable setIn element changes whole list
react: fade-in/slide-in animation when render component
ReactJS component vendors
css-loader, sass-loader not working webpack 2
The best way to organize your site ready for both PC and SP in reactjs, responsive or 2 sources?
Check data has already been fetched for react-redux in action, reducer or component?

Categories

HOME
optimization
phantomjs
cryengine
sahi
box-api
wkhtmltopdf
spring-data-solr
kairosdb
expo
cakephp-2.0
fastreport
hapijs
legend-properties
caldav
udeploy
single-page-application
custom-component
coccinelle
lotusscript
tcpdf
ng-tags-input
email-client
priority-queue
rollupjs
libxml2
marionette
large-files
checkmarx
dynamics-ax-2012-r3
federated
openoffice-impress
slim-lang
circle
flickr
restler
android-geofence
campaign-monitor
outlook-2010
console.readline
pygraphviz
iterm2
jquery-inputmask
google-cloud-powershell
aspnetboilerplate
contenteditable
paperclip
binary-decision-diagram
api-key
piranha-cms
weld
ack
togglebutton
pyopenssl
noise
audio-fingerprinting
visualizer
wink
fluent-nhibernate-mapping
playframework-1.x
ajv
typewriter
androiddesignsupport
apache-commons-cli
toggleclass
mongodb-3.3
symantec
git-cherry-pick
android-xmlpullparser
camellia
fadein
google-finance-api
dpkt
web-standards
service-broker
google-experiments
esri-arc-engine
switchpreference
pyalgotrade
ant-contrib
sendy
boofcv
ekevent
ardor3d
cab
proj4
spawn
aspmenu-control
event-propagation
pinchzoom
apache-commons-email
zend-validate
digg
response-time
quazip
html5-animation
database-agnostic
web-search
rpxnow
jettison
asp.net-1.1
tracd
paperless

Resources

Encrypt Message