簡體   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