#javascript #html #reactjs
Вопрос:
В React у меня есть таблица, в которой перечислены строки данных, и в каждой строке есть кнопка, которую я хочу вставить после нее и добавить компонент, позволяющий пользователю заполнить данные, а затем нажать сохранить, а затем удалить строку формы.
Это код, который я пробовал.
addRow = (idx) =gt; { const table = document.getElementById("allocatorTable"); const row = table.insertRow(idx 1); row.className = "editorRow"; const cell1 = row.insertCell(0); cell1.colspan = "10"; cell1.appenChild(lt;TransactionRuleEditor /gt;); };
Конечно, приложение lt;TransactionRuleEditor /gt; не будет работать, но оно дает вам представление о том, чего я пытаюсь достичь.
Я также попытался добавить форму в каждую строку и скрыть их. Но, конечно, у вас не может быть более одной формы на странице.
Есть идеи, пожалуйста? Малкольм
Комментарии:
1. Вы не мутируете DOM напрямую при использовании react. Измените состояние компонента и сделайте так, чтобы компонент всегда возвращал правильное представление состояния. Позвольте реакции применять мутации DOM так, как она хочет.
2. Просто для ясности
lt;TransactionRuleEditor /gt;
, это не элемент DOM или HTML. Эта строка будет скомпилирована в вызов функцииjsx(TransactionRuleEditor)
, которая возвращает POJO.3. Это классовый компонент. Я понимаю, о чем ты говоришь, но я все еще не знаю, как это объяснить.
Ответ №1:
Когда вы используете React (или любой другой фреймворк, подобный MVC), вы не работаете напрямую с DOM подобным образом, вы придерживаетесь другого мышления: вы меняете состояние того, что визуализируется, а затем фреймворк выполняет визуализацию. В этом случае у вас может быть компонент, предоставляющий строку таблицы, в состоянии, когда он фактически предоставляет две строки (завернутые во фрагмент) при нажатии кнопки.
Вот упрощенный пример:
const {useState, Component} = React; class Row extends Component { constructor(props) { super(props); this.state = { adding: false, }; this.onAdd = this.onAdd.bind(this); this.onDone = this.onDone.bind(this); } onAdd() { this.setState({adding: true}); } onDone() { // (Obviously you'd do more here) this.setState({adding: false}); } render() { const {adding} = this.state; const {data} = this.props; const row = lt;trgt; lt;tdgt;{data.a}lt;/tdgt; lt;tdgt;{data.b}lt;/tdgt; lt;tdgt;{data.c}lt;/tdgt; lt;tdgt;{!adding amp;amp; lt;input type="button" onClick={this.onAdd} value="Add" /gt; }lt;/tdgt; lt;/trgt;; if (!adding) { return row; } return lt;React.Fragmentgt; {row} lt;trgt; lt;td colSpan={3}gt; The inputs go here. lt;/tdgt; lt;tdgt; lt;input type="button" onClick={this.onDone} value="Done" /gt; lt;/tdgt; lt;/trgt; lt;/React.Fragmentgt;; } } // Or with hooks: // const Row = ({data}) =gt; { // const [adding, setAdding] = useState(false); // const row = lt;trgt; // lt;tdgt;{data.a}lt;/tdgt; // lt;tdgt;{data.b}lt;/tdgt; // lt;tdgt;{data.c}lt;/tdgt; // lt;tdgt;{!adding amp;amp; // lt;input type="button" onClick={() =gt; setAdding(true)} value="Add" /gt; // }lt;/tdgt; // lt;/trgt;; // if (!adding) { // return row; // } // // (You might memoize the callbacks via `useCallback`) // return lt;React.Fragmentgt; // {row} // lt;trgt; // lt;td colSpan={3}gt; // The inputs go here. // lt;/tdgt; // lt;tdgt; // lt;input type="button" onClick={() =gt; /* Obviously you'd do more here */ setAdding(false)} value="Done" /gt; // lt;/tdgt; // lt;/trgt; // lt;/React.Fragmentgt;; // } const Example = () =gt; { const [items] = useState([ {key: 1, a: "a1", b: "b1", c: "c1"}, {key: 2, a: "a2", b: "b2", c: "c2"}, {key: 3, a: "a3", b: "b3", c: "c3"}, ]); return lt;tablegt; lt;tbodygt; {items.map(item =gt; lt;Row key={item.key} data={item} /gt;)} lt;/tbodygt; lt;/tablegt;; }; ReactDOM.render(lt;Example /gt;, document.getElementById("root"));
td { width: 70px; }
lt;div id="root"gt;lt;/divgt; lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"gt;lt;/scriptgt; lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"gt;lt;/scriptgt;
(В этом примере используется lt;React.Fragmentgt;
, потому что версия Babel в фрагментах стека очень устарела, но в вашем реальном коде вы можете использовать lt;gt;
ее вместо этого.)
Конечно, это всего лишь набросок. Но это дает вам представление о том, как можно использовать состояние для обработки этой модальности.
Комментарии:
1. Спасибо большое за помощь. Я не мог изменить DOM напрямую, но не знал другого способа сделать это.