【问题标题】:Updating specific fields in reactJS更新 reactJS 中的特定字段
【发布时间】:2020-12-26 23:13:36
【问题描述】:

我有三个输入字段,每当我想更新特定字段而不是所有字段时,我没有修改的字段将在我的 mysql 数据库中返回空字符串 ('')。所以我的问题是让我的用户能够只修改他们需要的字段,而不会弄乱未触及的字段。当前默认值也是数据库中的当前值。我曾经能够修改目标字段,但我不能输入多个字符。这就是我使用 defaultValue 属性的原因。如果有人可以帮助我,我会非常高兴。 示例代码如下:

enter image description here

我的用户界面如下所示:

  interface User {
    fullName: string,
    email: string,
    password: string
  }

表格看起来像这样:

     <form method="put" className="updating_current_user" onSubmit={this.updateCuurentUser.bind(this, userId)}>
                <input type="hidden" value={userId}/>
                <input
                type="text"
                defaultValue={fullName}
                onChange={(e: any) => this.setState({ user: { ...user, fullName: e.target.value } })}
                required
               />
              <input
                type="email"
                defaultValue={email}
                onChange={(e: any) => this.setState(
                  { user: { ...user, email: e.target.value } })}
                />
              <input
                type="password"
                defaultValue={password}
                onChange={(e: any) => this.setState({ user: { ...user, password: e.target.value } })}
                required
              />
            </form>

对于 PUT 方法,我的快递后端是这样的:

app.put('/users/edit', (req, res) => {
    const { fullName, email, password, userId} = req.query

    const updateCurrentUser = `update users set fullName = '${fullName}', email = '${email}', password = '${password}' where userId = ${userId}`

    con.query(updateCurrentUser, (err, results) =>{
        if(err){
             res.redirect('/users')
        } else{
            res.send("Data updated...")
        }
    })
});

我的mysql数据库看起来:

create table if not exists users(
    userId INT NOT NULL auto_increment,  
    fullName VARCHAR(55), 
    email VARCHAR(55),
    password VARCHAR(55),
    PRIMARY KEY(userId)
);

我实际上并没有使用表单中的 onSubmit 函数。我是一个带有常规函数的按钮单击,其中 userId 作为唯一参数以更新数据库。我确实对 POST 做了同样的事情,我没有任何问题。所以这就是我的提交函数的样子:

  editUserInfo = (userId:number) => {
    const { user } = this.state
  
   fetch(`http://localhost:4000/users/edit?fullName=${user.fullName}&email=${user.email}&password=${user.password}&userId=${userId}`, {
        method: 'put',
      })
        .then(res => res.json()) 
         //this.getusers() to get all currently saved users in database
        .then(this.getUsers)
  }

我认为这就够了,或者我应该清楚得多!!!

【问题讨论】:

  • 请发布完整的相关代码,而不是代码图片
  • 我刚刚做了@Jayce444
  • 这里不一定看出有什么问题,但是您可以发布表单的完整状态以及您从前端发布的方式吗?我可以看到您在输入时传播了整个用户对象,但没有在状态对象的第一级复制任何其他内容
  • 我在 PostMan 中使用了相同的端点并且能够更新所有内容:http://localhost:4000/users/edit?fullName=${user.fullName}&amp;email=${user.email}&amp;password=${user.password}&amp;userId=${userId}
  • 我认为您所在州的整个“当前”值与用户对象的关系可能是您出错的地方。因为如果你加载页面,输入一个新的用户名,然后提交它,在 React 中电子邮件和密码最初是空字符串,所以空值将被发布到后端。我认为你不应该复制它们。而且你也没有展示你如何加载这些字段的用户初始值,我假设你是在装载时这样做的?

标签: javascript mysql reactjs typescript


【解决方案1】:

您的数据库查询字符串似乎会将未修改的字段更新为空字符串,而不管哪些字段具有值?也许您应该根据用户实际输入的字段有条件地构建查询:

app.put('/users/edit', (req, res) => {
    const { fullName, email, password, userId} = req.query

    // generate an array of {key, value} objects
    const mappedFields = [fullName, email, password, userId]
        .map((ea, i) => ({value: ea, key: ["fullName", "email", "password", "userId"][i]}));

    // this will be our query string
    let updateCurrentUser = '';

    // flag to track if we need to add comma to query string
    let multipleFieldsFlag = false;
    for(let ea in mappedFields) {
        if(ea.value) {
            if (!updateCurrentUser) {updateCurrentUser = 'update users set';}

            updateCurrentUser += multipleFieldsFlag ? ',' : '';
            updateCurrentUser += ` ${ea.key} = ${ea.value}`;

            multipleFieldsFlag = true;
        }
    }

    con.query(updateCurrentUser, (err, results) =>{
        if(err){
             res.redirect('/users')
        } else{
            res.send("Data updated...")
        }
    })
});

这样做的缺点是用户永远不能故意将字段设置为空字符串(因为在更新字段时会跳过它)。这对你来说可能是也可能不是问题,但如果是的话,这至少应该让你开始,你可以开始考虑如何处理这种特定的边缘情况,也许可以通过发送显式的 null 表单字段值前端。

【讨论】:

    【解决方案2】:

    我想出了一个更好的方法,我相信。我必须使用两个类组件,其中一个将充当父类并将数据发送到此处视为子组件的另一个组件,然后在完成所有用户修改后,所有数据,即使是未触及的数据,都将直接保存到backend 甚至更新 FrontEnd。在父类中,我立即一个接一个地使用了ComponentDidUpdateComponentDidMount。因此,现在即使页面已加载,我的所有期望也相应得到满足。问题是在同一个组件中有多个具有相同值名称的输入字段。我用来创建新项目的方法与我在应该更新现有项目的方法中使用的值名称完全相同;因此,每次我尝试更新现有数据时,应用程序都会使用创建新数据的方法触发字段,这使得除非我必须使用 defaultValue 属性,否则无法更新任何内容,结果默认值返回为空如果该字段是在未触及的情况下提交的,则为值。这些是我调试过程后的假设。我正要使用 react Context,但它已经可以使用了,所以,也许以后再说吧。

    
    interface UserState{
      currentUserInfo: any,
      users:Array<any>,
      user: {
        fullName: string,
        email: string
        password: string,
        userId: number
      },
    }
    //considers to be parent class
    export default class UserTimeline extends Component<{}, UserState>{
      constructor(props: UserState){
        super(props)
        this.state = { 
          users:[],
          currentUserInfo: {},
          user: {
            fullName: "",
            email: "",
            password: "",
            userId: 0
          }
         } 
      }
    
      componentDidUpdate = () => {
        this.updateUserInfo()
      }
      
      componentDidMount = () => {
        this.updateUserInfo()
      }
    
      updateUserInfo = () => {
        return this.state.user
      }
    
      
     
      //A method that will update existing data
      editCurrentUsers({ fullName, email, password, userId }: any) {
        return (
          <li key={userId}>
                <EditCurrent
                  currentUserInfo={{fullName, email, password, userId}}
                />
          </li>
        )
      }
    
     //will return these fields from users arrays
      renderCurrentUsers({ fullName, email, password, userId }: any) {   
        return (
          <li key={userId}>
            
          </li>
        )
      }
    
      render() {
        const { user, users } = this.state
        
        return (
          <Router>
            {/**/}
            </Router>
        );
      }
    }
    
    
    
    
    
    
    interface AllCurrentUser {
      currentUserInfo: any,
    }
    
    interface SingleCurrentUser{
        currentFullName: any,
        currentEmail: string,
      currentPassword: string,
      currentUserId: number
     }
    
    
    //considers to be child class Component
    class EditCurrent extends Component<AllCurrentUser, SingleCurrentUser>{
      constructor(props:any){
        super(props)
        this.state = {
            currentFullName: this.props.currentUserInfo.fullName,
            currentEmail: this.props.currentUserInfo.email,
            currentPassword: this.props.currentUserInfo.password,
            currentUserId: this.props.currentUserInfo.userId
        }
        this.updateFullName = this.updateFullName.bind(this);
        this.updateEmail = this.updateEmail.bind(this);
        this.updatePassword = this.updatePassword.bind(this);
        this.userDataGotUpdated = this.userDataGotUpdated.bind(this);
      }
      
      componentDidMount = () => {
        this.userDataGotUpdated()
      }
    
      userDataGotUpdated = () => {
        const { currentFullName, currentEmail, currentPassword, currentUserId } = this.state
    
        fetch(`http://localhost:4000/users/edit?fullName=${currentFullName}&email=${currentEmail}&password=${currentPassword}&userId=${currentUserId}`, {
          method: 'put',
        })
          .then(res => res.json()) 
          .catch(e => console.log(e))
      }
      
      updateFullName(event:any) {   
         this.setState({
           currentFullName: event.target.value,
         }); 
      }
    
      updateEmail(event:any) {   
         this.setState({
           currentEmail: event.target.value,
         }); 
      }
      
      updatePassword(event:any) {   
         this.setState({
           currentPassword: event.target.value
         }); 
      }
    
      render() {
        const { currentFullName, currentEmail, currentPassword, currentUserId } = this.state
        
        return (
          <div>
            <input type="hidden" value={currentUserId}  /> <br />
            <input type="text" value={currentFullName} onChange={this.updateFullName} /> <br />
            <input type="email" value={currentEmail} onChange={this.updateEmail} /> <br />
            <input type="password" value={currentPassword}
              onChange={this.updatePassword}
            /> <br />
            <button onClick={this.userDataGotUpdated}>
              <Link to="/users">Update</Link>
            </button>
          </div>
        );
      }
    }
    
    

    终于搞定了!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-23
      • 2017-11-30
      • 2012-12-03
      • 2021-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多