防止在 React 中提交时刷新页面

Preventing refresh page on submit in React

我正在尝试创建一个 editable table,它会在单击特定单元格后将其转换为 <input>,然后 运行 handleSubmit() 方法一旦用户按下 return.

下面是一个 <td> 单元格的示例,它使用 onClick 事件到 运行 handleClick() 方法并将其 <td></td> 转换为 <form><input></input></form>.

<td onClick={ e => this.handleClick(e)} style={{padding:'5px'}} key={cellID} id={cellID}>{frame.rows[i][idx]}</td>
      
 handleClick(e:React.MouseEvent<HTMLTableDataCellElement, MouseEvent>) {
    if(this.state.editing == false){          
      let form = `<form onSubmit=${ (e:any) => {this.handleSubmit(e)} } ><input type="text" value=${e.currentTarget.innerText} className="input-small gf-form-input width-auto"/></form>`
      e.currentTarget.innerHTML =  form;         
    }       
    this.setState({editing: true})
  }

 handleSubmit(e){
    e.preventDefault()        
  }

在这种情况下使用 e.preventDefault() 似乎不起作用。每次我在更改文本后按 return 时,页面都会刷新。在这种情况下如何阻止页面刷新?

您好,您可以像下面这样使用它:

1- 我假设您有一个如下所示的 return 按钮,因此您可以在 return 中提交而不使用表单提交事件:

_handleReturn(){
let val = document.getElementById("your input id");
//you can post above text to server if you want
   //Do Somthing
}
<button id="btn_return" onClick={this._handleReturn} />

2- 我没看到你在哪里触发 handleSubmit,但是提交表单会导致刷新,如果你不想的话,你应该使用 ajax。

我猜您想要实现一些功能,您可以在其中编辑列、修改或放弃更改,然后根据需要进行更新。

这个例子是本地状态,但你仍然可以通过获取数据来完成。

单击下面的 "运行 代码段" 以查看工作示例。

// main.js

const { useState } = React;

const App = () => {
  // State
  const [data, setData] = useState([{ id: 1, name: 'John', editing: false }, { id: 2, name: 'Kevin', editing: false }]);
   
  // Functions
  const onSubmitForm = index => event => {
    // To prevent form submission
    event.preventDefault();
    // To prevent td onClick
    event.stopPropagation();
    
    const newData = [...data];
    newData[index].name = newData[index].temp;
    newData[index].editing = false;
    delete newData[index].temp;
    setData(newData);
  }
  
  const onClickToggleEditing = index => event => {
    // To prevent td onClick and button conflicting with each other for toggling back on
    event.stopPropagation();
    
    const newData = [...data];
    newData[index].editing = !newData[index].editing;
    newData[index].temp = newData[index].name;
    setData(newData);
  }
  
  const onInputChange = index => event => {
    const newData = [...data];
    newData[index].temp = event.target.value;
    setData(newData);    
  }
   
  // Render
  // This basically like having its own component
  const editing = ( data, index, onChange, onSubmit, onCancel) => {  
    const onKeyUp = index => event => {
       if (event.key === 'Escape') {
        onCancel(index)(event);
       }
    }
  
    return <form onSubmit={onSubmit(index)}><input onKeyUp={onKeyUp(index)} onClick={e => e.stopPropagation()} type="text" value={data.temp} placeholder="Enter text" onChange={onChange(index)} /><button onClick={onSubmit(index)} type="submit">Save</button><button type="button" onClick={onCancel(index)}>Cancel</button></form>
  }
  
  return <main>
    <h1>Table Editing</h1>
    <p><small>Click to edit cell for <b>Name</b>.</small></p>
    <table>
      <thead>
        <tr>
        <th>ID</th>
        <th>Name</th>
        </tr>
      </thead>
        {data && data.length > 0 && <tbody>
           {data.map((i, k) => <tr key={`row-${k}`}>
            <td>{i.id}</td>
            <td className="editable" onClick={onClickToggleEditing(k)}>{i.editing ? editing(i, k, onInputChange, onSubmitForm, onClickToggleEditing) : i.name}</td>
          </tr>)}
      </tbody>}
    </table>
    
    <hr />
    <p><b>Data Manipulation:</b></p>
    <pre><code>{JSON.stringify(data, null, '\t')}</code></pre>
    
  </main>
}

ReactDOM.render(<App />, document.querySelector('#root'));
body {
  padding: 0;
  margin: 0;
  font-family: Arial,sans-serif;
}

main {
  padding: 0 20px;
}

h1 {
  font-size: 18px;
}


table {
  width: 100%;
  border-spacing: 0;
}

table tr td,
table tr th {
  border: 1px solid #efefef;
  height: 30px;
  line-height: 30px;
  text-align: left;
  padding: 6px;
}

table tr th:first-child {
  width: 100px;
}

.editable:hover {
  background: #efefef;
  cursor: pointer;
}

table input {
  height: 30px;
  line-height: 30px;
  font-size: 14px;
  padding: 0 6px;
  margin-right: 6px;
}

table button {
  height: 32px;
  border: none;
  background: red;
  color: white;
  font-size: 14px;
  padding: 0 10px;
  border-radius: 4px;
  margin-right: 5px;
  cursor: pointer;
}

table button[type=submit] {
  height: 32px;
  border: none;
  background: green;
  color: white;
  font-size: 14px;
  padding: 0 10px;
  border-radius: 4px;
}

hr {
  border: none;
  height: 1px;
  background: #999;
  margin: 20px 0;
}

pre {
  background: #efefef;
  padding: 6px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>


<div id="root"></div>

您的代码中存在一些问题。我最好修复它们,而不是尝试通过表单提交来修复问题。一旦完成,您将不必修复表单的问题 - 根本不会有任何问题。

首先,让我们看一下您的可编辑单元格:

<td onClick={ e => this.handleClick(e)} style={{padding:'5px'}} key={cellID} id={cellID}>{frame.rows[i][idx]}</td>

此元素应根据某些状态以不同方式呈现。我们可以使用 React 轻松实现这一点:

// JSX snippet
<td onClick={ e => this.handleClick(e)} 
    style={{padding:'5px'}} 
    key={cellID} id={cellID}>
    {this.state.editing ? <Input ... /> : <Label ... />}
</td>

我没有提供所有代码,因为我相信这些组件是不言自明的(欢迎您随意命名它们,我给它们起的名字非常简单,以明确它们的目的)。

  • <Input />封装了所有与编辑逻辑相关的东西
  • <Label /> 只是呈现文本或您需要的任何内容(可能 frame.rows[i][idx]
  • ... 意味着他们很可能会有一些 values/handlers 作为道具传递

在你的代码中,你有这个:

let form = `<form onSubmit=${ (e:any) => {this.handleSubmit(e)} } ><input type="text" value=${e.currentTarget.innerText} className="input-small gf-form-input width-auto"/></form>`

我认为它应该是一个独立的组件,有自己的状态和逻辑(例如提交)。事实上,这就是 <Input ... /> 在我的示例中的含义。如果你把它作为一个单独的组件 - 下面的代码将起作用(因为它将成为那个单独组件的一部分):

handleSubmit(e) {
  e.preventDefault()        
}

最后,避免做这样的事情:

e.currentTarget.innerHTML =  form;

重新考虑你的方法,你根本不需要做那样的事情。