无法输入反应输入字段 [英] unable to type in react input field

查看:50
本文介绍了无法输入反应输入字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我的输入字段的默认值是 1.如果我尝试在输入字段中输入内容,则没有任何变化.

interface Orders {order_graph_1:数量;order_graph_2:数量;}接口 MyProps 扩展订单 {setOrders: (...args: any) =>空白;//接受 args 的函数...??}接口 MyState 扩展订单 {//其他属性:字符串;}class Setup 扩展了 React.Component{状态 = {order_graph_1:this.props.order_graph_1,order_graph_2:this.props.order_graph_2};//需要是一个箭头函数才能正确访问 `this`//可以使用 ( event: React.ChangeEvent)//可以通过将名称作为参数传递来避免断言setOrders = (event: any) =>{this.setState((prevState) => ({...prevState,[event.target.name]: parseInt(event.target.value)}));};使成为(){返回(<div className="row"><div className="col-6"><p className="text-center">第一个模型的顺序:</p><div className="w-100 d-flex justify-content-center"><input className="text-center";名称=order_graph_1";类型=数字"value={this.props.order_graph_1} onChange={this.setOrders.bind(this)} min=1";max=10"/>

);}}导出默认设置;

为了测试,我改变了 onChange 函数

onChange={()=>console.log(你好")}

每次我尝试在输入字段中输入时,我都会在控制台中看到你好,但输入字段的值仍然没有改变.

这是一个 JS 代码 (https://github.com/MenesesGHZ/polynomial-regression-js):

class RegressionSetup 扩展 React.Component{构造函数(道具){超级(道具);this.orders = {order_graph_1":this.props.order_graph_1,order_graph_2":this.props.order_graph_2};}设置订单(事件){this.orders[event.target.name] = parseInt(event.target.value);this.props.setOrders(Object.values(this.orders));}使成为(){返回(<div className="row"><div className="col-6"><p className="text-center">第一个模型的顺序:</p><div className="w-100 d-flex justify-content-center"><input className="text-center";名称=order_graph_1";类型=数字"value={this.props.order_graph_1} onChange={this.setOrders.bind(this)} min=1";max=10"/>

<div className="col-6"><p className="text-center">第二个模型的顺序:</p><div className="w-100 d-flex justify-content-center"><input className="text-center"name="order_graph_2";类型=数字"value={this.props.order_graph_2} onChange={this.setOrders.bind(this)} min=1";max=10"/>

);}}导出默认的 RegressionSetup;

更改输入值后,图表上的一条线会根据该值发生变化.我不得不将此代码更改为 Typescript.这就是我现在所拥有的.

interface Orders {order_graph_1:数量;order_graph_2:数量;}接口 MyProps 扩展订单 {setOrders: (...args: any) =>空白;//接受 args 的函数...??}接口 MyState 扩展订单 {//其他属性:字符串;}class Setup 扩展了 React.Component{状态 = {//最好不要从 props 派生 stateorder_graph_1:this.props.order_graph_1,order_graph_2:this.props.order_graph_2};//需要是一个箭头函数才能正确访问 `this`//可以使用 ( event: React.ChangeEvent)//可以通过将名称作为参数传递来避免断言setOrders = (event: any) =>{//我不喜欢这个解决方案,但我们可以通过复制之前的状态来避免 TS 错误this.setState((prevState) => ({...prevState,[event.target.name]: parseInt(event.target.value)}));};使成为(){返回(<div className="row"><div className="col-6"><p className="text-center">第一个模型的顺序:</p><div className="w-100 d-flex justify-content-center"><input className="text-center";名称=order_graph_1";类型=数字"value={this.state.order_graph_1} onChange={this.setOrders.bind(this)} min=1";max=10"/>

{/*

<p className="text-center">第二个模型的顺序:</p><div className="w-100 d-flex justify-content-center"><input className="text-center"name="order_graph_2";类型=数字"value={this.props.order_graph_2} onChange={this.setOrders.bind(this)} min=1";max=10"/>

*/}

);}}导出默认设置;

虽然它编译没有错误,但输入值的东西不起作用.它不会改变图表上的线条,所以我假设状态没有被保存.我该如何解决这个问题?

解决方案

问题是您正在使用从 props 获得的 order_graph_1order_graph_2 的值,但是更新您在 state 中的那些,而不是更新 props 中的那些.

您正在转换的代码更新状态和道具(通过调用this.props.setOrders).但是完全没有必要让这些变量处于 RegressionSetup 的组件状态,因为它已经可以通过 props 访问和更新它们.

Main 组件也有点傻,因为这两个组件都有一个带有属性 order_graph_1order_graph_2<的状态/code> -- 那么为什么我们将它们作为元组传递给 setOrders?

Main 中,您可以删除 setOrders 函数,而是向下传递调用 setState 的箭头函数.

this.setState(orders)}/>

类组件中的

setState 获取部分新状态并将其与当前状态合并.这意味着我们甚至不必将 both 订单传递给 setOrders.我们只需一个订单就可以调用它,这很好.

所以我们可以像这样为我们的 RegressionComponent 定义道具:

导出接口 OrderGraphs {order_graph_1:数量;order_graph_2:数量;}接口道具扩展了 OrderGraphs {setOrders(graphs: Partial): void;}

没有理由让它成为一个类组件,但这也无所谓.RegressionSetup 不需要使用状态、钩子或生命周期方法.它只需要 props 并返回 JSX.

我仍然更喜欢使用函数来渲染两个输入,因为它的重复较少,但显然您不必这样做.我们使用变量 property 从 props value={this.props[property]} 获取正确的属性,并在传递给 的对象上设置正确的键代码>setOrders:onChange={(e) =>this.props.setOrders({[property]: parseInt(e.target.value, 10)})}

class RegressionSetup 扩展了 React.Component{renderInput(property: keyof OrderGraphs, label: string) {返回 (<div className="col-6"><p className="text-center">{label}</p><div className="w-100 d-flex justify-content-center"><输入className =文本中心";名称={属性}类型=数字"value={this.props[property]}onChange={(e) =>this.props.setOrders({ [property]: parseInt(e.target.value, 10) })}min=1"最大值=10"步骤=1"/>

);}使成为() {返回 (<div className="row">{this.renderInput("order_graph_1", "第一个模型的顺序:")}{this.renderInput("order_graph_2", "第二个模型的顺序:")}

);}}

代码沙盒链接

我也弄乱了其他组件.我为所有内容添加了 PropsState 类型.我还使用箭头函数来摆脱所有的 bind(this) 调用.还有一些与外部包(chart.js 和 mathjs)相关的 Typescript 错误.

Currently, the default value of my input field is 1. If I try to type something in the input field, nothing changes.

interface Orders {
    order_graph_1: number;
    order_graph_2: number;
  }

  interface MyProps extends Orders {
    setOrders: (...args: any) => void; // function which takes args...??
  }

  interface MyState extends Orders {
    //otherProperty: string;
  }
  
      

class Setup extends React.Component<MyProps, MyState>{
    state = {
        order_graph_1: this.props.order_graph_1,
        order_graph_2: this.props.order_graph_2
      };
    
      // needs to be an arrow function to access `this` properly
      // could use ( event: React.ChangeEvent<HTMLInputElement>)
      // could avoid the assertion by passing the name as an argument
      setOrders = (event: any) => {

        this.setState((prevState) => ({
          ...prevState,
          [event.target.name]: parseInt(event.target.value)
        }));
      };
    render(){
        return(
            <div className="row">
                <div className="col-6">
                    <p className="text-center">Order of first model: </p>
                    <div className="w-100 d-flex justify-content-center">
                        <input className="text-center" name="order_graph_1" type="number" value={this.props.order_graph_1} onChange={this.setOrders.bind(this)} min="1" max="10"/>
                </div>
                </div>
            </div>
        );
    }
}

export default Setup;

To test, I canged the onChange function

onChange={()=>console.log("hello")}

everytime I tried to type in the input field, I saw hello being printed in the console but the value of the input field still does not change.

edit:

This was a JS code (https://github.com/MenesesGHZ/polynomial-regression-js):

class RegressionSetup extends React.Component{
    constructor(props){
        super(props);
        this.orders = {
            "order_graph_1":this.props.order_graph_1,
            "order_graph_2":this.props.order_graph_2
        }; 
    }
    
    setOrders(event){
        this.orders[event.target.name] = parseInt(event.target.value);
        this.props.setOrders(Object.values(this.orders));
    }

    render(){
        return(
            <div className="row">
                <div className="col-6">
                    <p className="text-center">Order of first model: </p>
                    <div className="w-100 d-flex justify-content-center">
                        <input className="text-center" name="order_graph_1" type="number" value={this.props.order_graph_1} onChange={this.setOrders.bind(this)} min="1" max="10"/>
                </div>
                </div>
                <div className="col-6">
                    <p className="text-center">Order of second model: </p>
                    <div className="w-100 d-flex justify-content-center">
                        <input className="text-center"name="order_graph_2" type="number" value={this.props.order_graph_2} onChange={this.setOrders.bind(this)} min="1" max="10"/>
                    </div>
                </div>
            </div>
        );
    }
}

export default RegressionSetup;

Upon changing the value of input, a line on a graph changed according to the value. I had to change this code to Typescript. This is what I have now.

interface Orders {
    order_graph_1: number;
    order_graph_2: number;
  }

  interface MyProps extends Orders {
    setOrders: (...args: any) => void; // function which takes args...??
  }

  interface MyState extends Orders {
    //otherProperty: string;
  }
  
      

class Setup extends React.Component<MyProps, MyState>{
    state = {
        // it is best not to derive state from props
        order_graph_1: this.props.order_graph_1,
        order_graph_2: this.props.order_graph_2
      };
    
      // needs to be an arrow function to access `this` properly
      // could use ( event: React.ChangeEvent<HTMLInputElement>)
      // could avoid the assertion by passing the name as an argument
      setOrders = (event: any) => {
        // I don't love this solution, but we can avoid the TS errors by copying the previous state
        this.setState((prevState) => ({
          ...prevState,
          [event.target.name]: parseInt(event.target.value)
        }));
      };
    render(){
        return(
            <div className="row">
                <div className="col-6">
                    <p className="text-center">Order of first model: </p>
                    <div className="w-100 d-flex justify-content-center">
                        <input className="text-center" name="order_graph_1" type="number" value={this.state.order_graph_1} onChange={this.setOrders.bind(this)} min="1" max="10"/>
                </div>
                </div>
                {/* <div className="col-6">
                    <p className="text-center">Order of second model: </p>
                    <div className="w-100 d-flex justify-content-center">
                        <input className="text-center"name="order_graph_2" type="number" value={this.props.order_graph_2} onChange={this.setOrders.bind(this)} min="1" max="10"/>
                    </div>
                </div> */}
            </div>
        );
    }
}

export default Setup;   

although it compiles without an error, the input value thing is not working. It does not change the line on the graph so I am assuming the state is not saved. How can I fix this?

解决方案

The problem is that you are using the value of order_graph_1 and order_graph_2 that you get from props but updating the ones that you have in state and not updating the ones in the props.

The code that you are converting updates both the state and the props (by calling this.props.setOrders). But it is totally unnecessary to have these variables in a component state of RegressionSetup at all since it can already access and update them through props.

The setOrders function which is passed down from the parent Main component is also a bit silly because both components have a state with properties order_graph_1 and order_graph_2 -- so why are we passing them as a tuple to setOrders?

In Main you can delete the setOrders function and instead pass down an arrow function that calls setState.

<RegressionSetup
  order_graph_1={this.state.order_graph_1}
  order_graph_2={this.state.order_graph_2}
  setOrders={(orders) => this.setState(orders)}
/>

setState in a class component takes a partial new state and merges it with the current state. That means the we don't even have to pass both orders to setOrders. We can call it with just one order and that's fine.

So we can define the props for our RegressionComponent like this:

export interface OrderGraphs {
  order_graph_1: number;
  order_graph_2: number;
}

interface Props extends OrderGraphs {
  setOrders(graphs: Partial<OrderGraphs>): void;
}

There is no reason for it to be a class component, but it also doesn't matter. RegressionSetup does not need to use state, hooks, or lifecycle methods. It just takes props and returns JSX.

I still prefer to render the two inputs using a function since it's less repetition but obviously you don't have to do that. We use the variable property to get the correct property from props value={this.props[property]} and to set the correct key on the object that we pass to setOrders: onChange={(e) => this.props.setOrders({[property]: parseInt(e.target.value, 10)})}

class RegressionSetup extends React.Component<Props> {
  renderInput(property: keyof OrderGraphs, label: string) {
    return (
      <div className="col-6">
        <p className="text-center">{label}</p>
        <div className="w-100 d-flex justify-content-center">
          <input
            className="text-center"
            name={property}
            type="number"
            value={this.props[property]}
            onChange={(e) =>
              this.props.setOrders({ [property]: parseInt(e.target.value, 10) })
            }
            min="1"
            max="10"
            step="1"
          />
        </div>
      </div>
    );
  }

  render() {
    return (
      <div className="row">
        {this.renderInput("order_graph_1", "Order of first model: ")}
        {this.renderInput("order_graph_2", "Order of second model: ")}
      </div>
    );
  }
}

Code Sandbox Link

I messed with the other components as well. I added Props and State types for everything. I also used arrow functions to get rid of all the bind(this) calls. There are still a few Typescript errors related to the external packages (chart.js and mathjs).

这篇关于无法输入反应输入字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆