假设我有一个组件类负责将输入文本框的任何数字更改为文字:
class NumbersToText extends Component {
onChange(event) {
const { target } = event;
const { value } = target;
if (hasNumbers(value)) {
target.value = numbersToText(value);
// HERE I NEED TO NOTIFY ABOUT CHANGES
}
}
render() {
return (
<span onChange={this.onChange}>
{this.props.children}
</span>
);
}
}
现在用法看起来像这样:
<NumbersToText>
<input onChange={this.saveValue}
</NumbersToText>
让我们说一切正常,价值变为文字。
现在问题是在我将数字更改为文本并将该值分配给输入onChange
之后,处理程序不会再次执行,因此不会使用更新的值调用saveValue
如何使用新值触发onChange
处理程序来解决此问题?
答案 0 :(得分:0)
我不确切地知道numbers to text
到底是什么意思所以我假设您想在输入中调用onChange函数之前修改该值,并在输入中反映该值。
首先,你正在做的事情永远不会在React上运行,React将内部virtual
对象反映到DOM中,这意味着你不应该直接修改DOM,而应该修改这个内部表示(通过setState) ,props)将此更改反映到DOM中。
React还有两种类型的输入,控制和非控制。我假设你想在不受控制的输入上使用它。
我能看到的唯一可行解决方案是使用React.cloneElement
函数转换输入,在调用输入的onChange
回调之前添加一个附加步骤。
这是一个可能使输入变为大写的实现。
class UpperCase extends React.Component {
constructor(props) {
super(props);
}
onChange(e, input, next) {
let value = input.value || '';
value = value.toUpperCase();
input.value = value;
next(value);
}
render() {
let childs = React.Children.map(this.props.children, child => {
let input = null; //Will take advantage of javascript's closures
let onChangeChild = child.props.onChange.bind(child);
return React.cloneElement(child, {
ref: ref => input = ref,
onChange: e => {
this.onChange(e, input, onChangeChild)
}
});
});
return (
<span>
{childs}
</span>
);
}
}
你可以像这样使用它:
<UpperCase>
<input onChange={(val) => console.log(val)}></input>
<textarea onChange={(val) => console.log(val)}></textarea>
</UpperCase>
答案 1 :(得分:0)
感谢@tiagohngl,我想出了一个类似的,但也许不那么杂乱(没有克隆元素)的方式:
class NumbersToText extends Component {
onChange(event) {
const { target } = event;
const { value } = target;
if (hasNumbers(value)) {
target.value = numbersToText(value);
this.childrenOnChange(event);
}
}
childrenOnChange(event) {
const { children } = this.props;
React.Children.forEach(children, child => {
if (child.props.onChange) {
child.props.onChange(event);
}
});
}
render() {
return (
<span onChange={this.onChange}>
{this.props.children}
</span>
);
}
}
答案 2 :(得分:0)
export default class NumbersToText extends React.Component {
constructor(props) {
super(props)
this.onChange = this.onChange.bind(this);
}
componentWillMount() {
this.setState({ anyData: [] });
}
onChange(event) {
this.setState({anyData: event.target.value},
()=>{console.log("AnyData: "+this.state.anyData)});
// callback to console.log after setState is done
}
render() {
return (
<input type="text"
value={this.state.anyData}
onChange={this.onChange} />
);
}
}
如你所说, 更改后的值不会调用onChange。
有多种可能性。
onChange没有绑定。
渲染方法没有状态更改,因此不会重新渲染
使用console.log()来追踪问题
我稍微修改了代码以供说明。
希望它有所帮助。