簡體   English   中英

在提交/輸入不起作用后,React.js專注於文本輸入

[英]React.js focus on text input after submit/enter not working

我有一個組件,當用戶點擊提交(或輸入)一個新問題時,文本輸入就會顯示出來,用戶輸入一個答案,然后點擊提交(這一直重復到最后一個問題得到回答為止)。

除我不添加參考或自動對焦外,其他所有功能均不對焦。 我不確定在此關頭該做什么,而且無論我如何嘗試,似乎都無法使其正常工作。

我可以得到一些幫助嗎,當用戶點擊“提交”時,它將專注於下一個文本輸入。 我在代碼中使用下面的樣式化組件,因此文本輸入將為inputStyle

 class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
    this.state = {
      value1: '',
      value2: '',
      value3: '',
      value4: '',
      value5: '',
      value6: '',
      value7: '',
      newValue: '',
      submitted: false,
      input1: 0,
      input2: 0,
      input3: 0,
      input4: 0,
      input5: 0,
      input6: 0,
      input7: 0,
      display: 'block',
      currentStep: 1,
      whitebox: 'block'
    };

    this.handleFirstChange = event => this.handleChange(event, 'value1');
    this.handleSecondChange = event => this.handleChange(event, 'value2');
    this.handleThirdChange = event => this.handleChange(event, 'value3');
    this.handleFourthChange = event => this.handleChange(event, 'value4');
    this.handleFifthChange = event => this.handleChange(event, 'value5');
    this.handleSixthChange = event => this.handleChange(event, 'value6');
    this.handleSeventhChange = event => this.handleChange(event, 'value7');
    this.handleSubmit = event => this._handleSubmit(event);
  }

  handleChange(event, type) {
    let newState = {};
    newState[type] = event.target.value;
    this.setState(newState);
  }

  _handleSubmit(event) {
    event.preventDefault();
    if (this.state.currentStep > 6) {
      this.setState({ visible: !this.state.visible });
      this.setState({ display: 'none' });
      this.setState({ whitebox: 'none' });
    } else {
      this.setState({ currentStep: this.state.currentStep + 1 });
    }
  }

  inputHolderStyle(style, step) {
    const displayProp = step === this.state.currentStep ? 'block' : 'none';

    return {
      // background: `url(${style}) no-repeat center center`,
      // backgroundSize: 'cover',
      // border: 'white 1px solid',
      // background: '#00B5DE',
      display: displayProp
    };
  }

  focus() {
    // Explicitly focus the text input using the raw DOM API
    this.textInput.focus();
  }

  render() {
    const divStyle = {
      marginTop: '50px',
      color: 'white',
      top: '25px',
      position: 'absolute',
      width: '320px',
      textAlign: 'center',
      border: 'white 1px solid',
      padding: '1em',
      borderRadius: '3px',
      display: this.state.whitebox
    };
    let question = null;
    const show = this.state.visible;
    if (show) {
      question = (
        <div>
          <Crawler
            properName1={this.state.value1}
            noun1={this.state.value2}
            properName2={this.state.value3}
            properName3={this.state.value4}
            noun2={this.state.value5}
            personsName1={this.state.value6}
            noun3={this.state.value7}
          />
        </div>
      );
    }
    return (
      <MainContainer>
        <div style={divStyle}>
          <form
            style={{ display: this.state.display }}
            onSubmit={this.handleSubmit}
          >
            <InputHolder style={this.inputHolderStyle(ml1, 1)}>
              <InputQuestion>1. Enter A Proper Noun</InputQuestion>
              <label>
                <InputStyle
                  name="input1"
                  type="text"
                  value={this.state.value1}
                  placeholder="Proper Noun"
                  onChange={this.handleFirstChange}
                  ref1={input => {
                    this.textInput = input;
                  }}
                />
                <GrammarNerd>
                  Hint: Use words like Rebel, Hell's Angels, Vegan
                </GrammarNerd>
              </label>
            </InputHolder>
            <InputHolder style={this.inputHolderStyle(ml2, 2)}>
              <InputQuestion>2. Enter A Location</InputQuestion>
              <label>
                <InputStyle
                  name="input2"
                  type="text"
                  ref={input => {
                    this.textInput = input;
                  }}
                  value={this.state.value2}
                  placeholder="Noun"
                  onChange={this.handleSecondChange}
                  ref2={input => {
                    this.textInput = input;
                  }}
                />
                <GrammarNerd>
                  Hint: Use a word such as Base, Bunker, Foxhole, Bedroom
                </GrammarNerd>
              </label>
            </InputHolder>
            <InputHolder style={this.inputHolderStyle(ml3, 3)}>
              <InputQuestion>
                Enter A Proper Noun that Describes Evil
              </InputQuestion>
              <label>
                <InputStyle
                  name="input3"
                  type="text"
                  placeholder="Enter a Proper Noun"
                  value={this.state.value3}
                  onChange={this.handleThirdChange}
                  ref3={input => {
                    this.textInput = input;
                  }}
                />
              </label>
              <GrammarNerd>
                Hint: Use words like Empire, Ottoman, Mongols
              </GrammarNerd>
            </InputHolder>
            <InputHolder style={this.inputHolderStyle(ml3, 4)}>
              <InputQuestion>Describe Something Menacing</InputQuestion>
              <label>
                <InputStyle
                  name="input4"
                  type="text"
                  placeholder="Enter a Proper Name"
                  value={this.state.value4}
                  onChange={this.handleFourthChange}
                  ref4="theDiv"
                />
                <GrammarNerd>
                  Hint: Freeze Ray, Mother of All Bombs, Leftover Fruitcake
                </GrammarNerd>
              </label>
            </InputHolder>
            <InputHolder style={this.inputHolderStyle(ml3, 5)}>
              <InputQuestion>Describe a fortified area</InputQuestion>
              <label>
                <InputStyle
                  name="input5"
                  type="text"
                  placeholder="Enter a Noun"
                  value={this.state.value5}
                  onChange={this.handleFifthChange}
                  ref5={input => {
                    this.textInput = input;
                  }}
                />
                <GrammarNerd>
                  Hint: Castle, Bunker, Planet, Safe Space
                </GrammarNerd>
              </label>
            </InputHolder>
            <InputHolder style={this.inputHolderStyle(ml3, 6)}>
              <InputQuestion>A Woman's Name</InputQuestion>
              <label>
                <InputStyle
                  name="input6"
                  type="text"
                  placeholder="A Woman's Name"
                  value={this.state.value6}
                  onChange={this.handleSixthChange}
                  ref6={input => {
                    this.textInput = input;
                  }}
                />
              </label>
              <GrammarNerd>
                Hint: Astrid, Diana, Mononoke, Peach{' '}
              </GrammarNerd>
            </InputHolder>
            <InputHolder style={this.inputHolderStyle(ml3, 7)}>
              <InputQuestion>Describe a large area of mass</InputQuestion>
              <label>
                <InputStyle
                  name="input7"
                  type="text"
                  placeholder="Enter a Noun"
                  value={this.state.value7}
                  onChange={this.handleSeventhChange}
                  ref7={input => {
                    this.textInput = input;
                  }}
                />
              </label>
              <GrammarNerd>
                Galaxy, Planet, Wal Mart
              </GrammarNerd>
            </InputHolder>
            <InputHolderSubmit>
              <SubmitButton onClick={this.focus} type="submit" value="Submit" />
            </InputHolderSubmit>
          </form>
        </div>
        <NextQuestion>
          {question}
        </NextQuestion>
      </MainContainer>
    );
  }
}

export default NameForm;

我留下了一些我已經測試過的代碼(ref和autofocus),以及一些似乎沒有破壞代碼,但也不起作用的功能。

謝謝您的幫助

自動對焦演示的工作示例

以下代碼是您要執行的操作的簡化示例實現。...簽出並運行它,讓我知道這是否有幫助!!! 快樂的編碼=]!

import React, { Component } from "react";

export default class AutoFocusText extends Component {
    constructor() {
        super();

        this.state = {
            active: 0,
            questions: [
                "how are you?",
                "whats your name?",
                "is reactjs awesome?"
            ],
            value: "",
            answers: []
        };

        this.submitHandler = this.submitHandler.bind(this);
        this.renderQuestion = this.renderQuestion.bind(this);
        this.onChange = this.onChange.bind(this);
    }

    renderQuestion() {
        const { questions, active, value } = this.state;

        if (active >= questions.length) return <div>You're Done!</div>;

        return questions
            .filter((quest, index) => index === active) // get next question
            .map(quest =>    // map over selected question, the key prop allows react to
                <FormElement // unmount and mount the components properly, thereby focussing correctly
                    key={active}
                    text={quest}
                    value={value}
                    onChange={this.onChange}
                />
            );
    }

    onChange(e) {
        this.setState({ value: e.target.value });
    }

    submitHandler(e) {
        e.preventDefault();

        const answers = [...this.state.answers, this.state.value]; //push new value to answsers array without mutation
        const value = ""; // clear input
        const active = this.state.active + 1; // index pointer

        this.setState({ answers, value, active });
    }

    render() {
        return (
            <div>
                {/* Form Wrapper */}
                <form onSubmit={this.submitHandler}>
                    {this.renderQuestion()}
                    <button type="submit">Submit</button>
                </form>
                <ul>
                    {this.state.answers.map((ans, index) => {
                        return (
                            <li key={index}>
                                {ans}
                            </li>
                        );
                    })}
                </ul>
            </div>
        );
    }
}

這是用於管理文本輸入焦點的FormElement組件。

class FormElement extends Component {
    constructor() {
        super();
    }

    componentDidMount() {
        //focus text input upon mounting component 
        this.textInput.focus();
    }

    render() {
        const { text, value, onChange } = this.props;

        return (
            <div>
                <p>
                    {text}
                </p>
                <input
                    ref={el => {
                        this.textInput = el;
                    }}
                    onChange={onChange}
                    type="text"
                    value={value}
                />
            </div>
        );
    }
}

要進行修復,請考慮以下內容

  1. 由於您使用display:none隱藏每個問題,因此它們仍會呈現到DOM中,因此無論您在哪個問題上,都會執行每個ref。 您將分配給this.textInput,因此this.textInput將僅具有input7的元素。
  2. 出於同樣的原因,自動對焦可能無法很好地工作,因為我相信當將React組件添加到DOM(在CSS中不可見)時會觸發自動對焦。

如果我是你,我會與switch語句,它返回JSX的步驟每種情況下renderQuestion( 步驟 )方法。 使用{this.renderQuestion(step)}在您的主要render方法中的form元素之后調用此命令,進行切換,這樣僅活動的問題將被呈現到DOM中。 我不確定這可能有助於使autoFocus正常工作。 但更明確地說,ref現在可以正常工作,您只需

componentDidUpdate() {
  this.textInput && this.textInput.focus();
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM