繁体   English   中英

在事件中创建和显示新元素 (React.JS)

[英]Creating and displaying new elements on event (React.JS)

自从我开始编程以来,过去两年我一直在使用堆栈溢出,但我从来没有直接问过问题。 然而,最近我在使用 React 时遇到了一个问题,这让我在上周感到困惑,感觉就像是专业人士会看到并立即知道答案的问题之一。

我的代码: https://codepen.io/gooeyWolf/pen/xxZGxGq

 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <body> <div id="root"><div id="shit"></div></div> <script src="https://unpkg.com/react@16.12.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.12.0/umd/react-dom.development.js"></script> <script src="https://unpkg.com/@babel/standalone@7.8.3/babel.js"></script> <script type="text/babel"> class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: '',}; this.handleChange = this.handleChange.bind(this); } NextThing(){ const element = <h1>Hello, world;</h1>. const divy = document.body;getElementById("div2"). divy;appendChild(element). //document.body;appendChild(element). } handleChange(event) { this:setState({value. event.target;value}). } handleEnter(event){ if(event.key === 'Enter'){ this;NextThing(), } } render() { return ( <div> <span>Are you writing for a protagonist, antagonist, love interest? or secondary character. <br /></span> <input name="flip" id="lucky" value={this.state.value} onChange={this.handleChange} onKeyDown={this;handleEnter} /> <div id="div2"></div> </div> ). } } //onChange={this.handleChange} ReactDOM,render( <NameForm />. document;getElementById('root') ); </script> </body>

我正在构建的应用程序非常简单。 基本上,该应用程序会问您一个问题,您输入答案,然后它会显示一个新的文本块和一个新的输入框来输入您的下一个答案,同时将之前的文本留在屏幕上。 到目前为止,当您键入内容并按下回车时,程序会处理回车,并调用另一个 function 来显示下一个文本块。 起初,我尝试使用 return/render 语句,但这会导致页面刷新,这很好,但是我想显示的新元素没有显示出来。 我正在学习的 React.JS 课程建议不要对所需的每个新元素使用creatElement语句,因此我正在使用appendChild ,由于某种原因,这会出现错误。 我觉得必须有一个更简单的解决方案,以及一个更可重用的解决方案。 理想情况下,它将能够处理刷新并保留先前添加的元素。 我首先在 python 中编写了这个程序,使用 print 和 input 语句,这很容易,但我花了上周试图找出 React 的正确方法,但我所有的解决方案似乎都不必要地复杂。 必须有更好的方法......非常感谢你们,这比我能表达的更有用。 堆栈溢出最好(:

在 React 中,常见的 DOM 操作函数( appendChildinnerHtml等)不是做到这一点的“最佳”方式,正如你所说,有一个更有用的解决方案。 您可以做的是利用 JavaSript 表达式可以在HTML中呈现的方式(即,带有{{variable}}和花括号的那些)并将其与this.state结合起来。

首先在this.state中,定义一个数组div2Children ,它将包含输入到输入中的所有文本

// This is inside the constructor
this.state = {value: '', div2Children: []};

然后您可以通过每个元素map并在 HTML 中转换它们。

render() {
    return (
        <div>
            <span>Are you writing for a protagonist, antagonist, love interest, or secondary character? <br /></span>
            <input name="flip" id="lucky" value={this.state.value} onChange={this.handleChange} onKeyDown={this.handleEnter} />
            <div id="div2">
                {/* when the array changes this page will also change the HTML */}
                {this.state.div2Children.map(child => (
                    <h1>{child}</h1>
                ))}
            </div>
        </div>
    );
}

然后最后在NextThing方法中,您必须使用div2Children this.setState以包含所有先前的元素,但也包含新类型(附加最后一个元素但创建一个新数组)

NextThing(){
    this.setState({div2Children : [...this.state.div2Children, this.state.value]});
}

请注意,您还必须绑定NextThinghandleChange 这是一个工作版本

 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <body> <div id="root"><div id="shit"></div></div> <script src="https://unpkg.com/react@16.12.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.12.0/umd/react-dom.development.js"></script> <script src="https://unpkg.com/@babel/standalone@7.8.3/babel.js"></script> <script type="text/babel"> class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: '', div2Children: []}; // Bind all the functions this.NextThing = this.NextThing.bind(this); this.handleChange = this.handleChange.bind(this); this.handleEnter = this.handleEnter.bind(this); } NextThing(){ this.setState({div2Children: [...this.state.div2Children, this.state.value]}); } handleChange(event) { this.setState({value: event.target.value}); } handleEnter(event){ if(event.key === 'Enter'){ this.NextThing(); } } render() { return ( <div> <span>Are you writing for a protagonist, antagonist, love interest, or secondary character? <br /></span> <input name="flip" id="lucky" value={this.state.value} onChange={this.handleChange} onKeyDown={this.handleEnter} /> <div id="div2"> {this.state.div2Children.map((child, index) => ( <h1 key={index}>{child}</h1> ))} </div> </div> ); } } //onChange={this.handleChange} ReactDOM.render( <NameForm />, document.getElementById('root') ); </script> </body>

另请注意,我还在上面的代码段中设置了一个key属性。 你可以在这里找到更多相关信息,我只是提供了一个简单的解决方案,应该没问题。

首先,你不能像 React 那样访问 DOM 元素。 检查参考反应 API。 无论如何,我认为你应该在这里扭转你的反思并避免那些 dom 操纵(如果可以的话)。

数据应该足以显示问题和答案。

 class NameForm extends React.Component {
   constructor(props) {
     super(props);
     this.state = {
       step: 1,
       values: [''],
       questions: [
         {
           id: 1,
           label: 'Are you writing for a protagonist, antagonist, love interest, or secondary character?',
         },
         {
           id: 2,
           label: 'Are you happy?',
         }
         // other questions
       ]};
   }
   NextThing = (next) => {
     this.setState((prev) => ({step: prev.step+1, values: [...prev.values, '']}));
   }
   handleChange = (index, event) => {
     event.persist()
     this.setState(state => {
       const values = state.values.map((item, j) => {
         if (j === index) {
           return event.target.value;
         } else {
           return item;
         }
       });

       return {
         values,
       };
     });
   }
   handleEnter = (index, event) => {
     if(event.key === 'Enter' && this.state.step < this.state.questions.length){
       this.NextThing(index);
     }
   }

   render() {
     const { questions, step, values } = this.state;

     return (
       <div>
         {questions.slice(0, step).map((question, index) => (
           <div key={question.id}>
             <span>{question.label}<br /></span>
             <input 
               name={"answer"+question.id} 
               id={"answer"+question.id}
               value={values[index]} 
               onChange={e => this.handleChange(index, e)} 
               onKeyDown={e => this.handleEnter(index, e)} />
           </div>
         ))}
       </div>
     );
   }
 }

ReactDOM.render(
  <NameForm />,
  document.getElementById('root')
);

让我知道我是否误解了某些内容或是否有帮助:D

正如其他人所写,您不应该尝试像 React 中的常规 javascript 那样操作 DOM。

所以; 我们不应该像普通的 js 那样操作元素,但我们可以做的是我们可以用 Refs 和 States 改变 HTML 里面的东西。 您可以使用 ref 以 React 方式为元素赋予某种“id”,并更改其属性。 State 是 React 的关键元素之一,它非常强大。

https://reactjs.org/docs/state-and-lifecycle.html

我们可以打开和关闭 div、输入和其他元素的可见性、innerTexts 等。

https://reactjs.org/docs/hooks-state.html

我将使用 State Hook 在这里更改 div 的显示:

const [testState, setTestState] = useState(false)

...

return (
<>
    <h1>Example Page</h1>
    {testState ? <input placeholder="Example Input" /> : null}
</>
)

如果我的 testState 为真; 会出现一个输入框; 如果它是假的,什么都不会。 我们现在可以在代码中的某处使用 setTestState(true) - 或 false- 来更改呈现 html 块的可见性。

现在,不确定我是否正确理解了您的问题和 phyton 代码(我可能没有),我很快做了一个演示,使用状态来切换元素的可见性。

https://codesandbox.io/s/zealous-taussig-0ctif

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM