簡體   English   中英

React Stepper 使用獲取的狀態列表作為下拉選項到下一步 - 無法讀取未定義的屬性“地圖”

[英]React Stepper use fetched list in state to next step as dropdown options - Cannot read property 'map' of undefined

我是 React 的新手,正在創建一個 Stepper(向導)表單,如此數字海洋鏈接所示: https : //www.digitalocean.com/community/tutorials/how-to-create-multistep-forms-with-react -and-semantic-ui

我改變了那個例子......相反,前兩個步驟每個都只有一個下拉選項。 在第一步中,下拉列表是從我的第一個 axios 獲取生成的,我希望第二個步驟中的第二個下拉列表顯示基於第一個選擇的選項。 (為簡單起見,這里假設第 1 步選項只是值 1、2 或 3 的列表)

我的問題是我無法將我的過濾列表 (objectsListOptionsForStep2) 轉移到下一步,因為我有這個錯誤: TypeError: Cannot read property 'map' of undefined ...我的變量 (objectsListOptionsForStep2) 在我去的時候似乎是未定義的從第 1 步到第 2 步,因此我無法在下拉列表中將列表顯示為選項。

在 MainForm 中,我首先調用 axios 並將數據置於狀態。 然后,當我在第一步的第一個下拉列表中選擇第一個選項並完成后,我調用我的 handleChange,在其中我獲取所選的值,並有條件地調用 axios(如果步驟為 =1),並將值選為選項。

在第二步中,我無法將過濾后的列表用作選項......我有前面描述的這個錯誤。

有人可以解釋或告訴我如何逐步使我的列表處於狀態嗎? 非常感謝 !!!

這是 MainForm.js

export class WizardMainForm extends Component {

  state = {
    error: null,
    step: 1,
    choiceOne: "",
    choiceTwo: "",
    objectsListOptionsForStep2: []
  };

  componentDidMount() {
    this.handleUserDetails();
  }

  handleUserDetails = () => {
     some code here
  };

  
  // Proceed to the next step
  nextStep = () => {
    const { step } = this.state;
    this.setState({
      step: step + 1,
    });
  };

  // Go back to previous step
  prevStep = () => {
    const { step } = this.state;
    this.setState({
      step: step - 1,
    });
  };

  //Handle fields change
  handleChange = (input) => (e) => {
    this.setState({ [input]: e.target.value });
    if (this.state.step == 1){
      const valueSelectedAtStepOne = e.target.value
      authAxios
      .get(`myUrl/?q=${valueSelectedAtStepOne}`)
      .then((res) => {
        this.setState({
          objectsListOptionsForStep2: res.data,
        });
        console.log(res.data);
      })
      .catch((err) => {
        this.setState({
          error: err.response.data.message,
        });
      });
    }
  };


  render() {
    const { step, choiceOne, objectsListOptionsForStep2 } = this.state;
    
    const values = {choiceOne, choiceTwo};
    
    switch (step) {
      case 1:
        return (
          <FormChoiceOne
            nextStep={this.nextStep}
            values={values}
            handleUserDetails={this.handleUserDetails}
            handleChange={this.handleChange}
          />
        );
      case 2:
        return (
          <FormChoiceTwo
            nextStep={this.nextStep}
            prevStep={this.prevStep}
            values={values}
            handleUserDetails={this.handleUserDetails} 
            handleChange={this.handleChange}
          />
        );
    }
  }
}

export default WizardMainForm;

這里如果 FormChoiceOne.js

    export class FormChoiceOne extends Component {
      
        continue = (e) => {
        e.preventDefault();
        this.props.nextStep();
      };
    
      render() {
       return (
        <div>
         <Form>
            <select
              onChange={handleChange("choiceOne")}
              defaultValue={values.choiceOne}
            >
              <option>1</option>
              <option>2</option>
              <option>3</option>
            </select>
            <Button onClick={this.continue}> Next step </Button>
         </Form>
        </div>
    );
  }
}

export default FormChoiceOne;

這是 FormChoiceTwo.js 這是我遇到問題的地方...

export class FormChoiceTwo extends Component {

continue = (e) => {
    e.preventDefault();
    this.props.nextStep();
  };

  back = (e) => {
    e.preventDefault();
    this.props.prevStep();
  };

render() {
    
some code

    return (
      <div>
       <Form>
        <select>
          {this.objectsListOptionsForStep2.map((u) => (
            <option>{u.id}</option>
          ))}
         </select>
            <Button onClick={this.back}> Previous step </Button>
            <Button onClick={this.continue}> Next step </Button> 
       </Form>
      </div>
    );
  }
}


export default FormChoiceTwo;

根據你的評論試試這個:

{
(objectsListOptionsForStep2 === null || objectsListOptionsForStep2===undefined) ? 
    <option>Loading</option> : 
    this.objectsListOptionsForStep2.map((u) => (
            <option>{u.id}</option>
          ))
}

告訴我現在發生了什么。 並嘗試在codeandbox.io創建一個沙箱

根據你在沙箱中的代碼,我在這里編輯: https : //codesandbox.io/s/silly-swirles-kv61w?file=/ src/MainForm.js: 852-878 我可以告訴你

  • 問題出在 API
  • https://swapi.dev/api/planets/{value}/返回 HTML,但它應該返回 JSON,現在我們必須以某種方式解析。
  • 您從未將objectsListOptionsForStep2傳遞給 Form2
  • 並且您必須在為該對象獲取值后等待觸發,然后才能渲染
  • 不需要使用這個,現在我可以理解你的代碼了

如果您可以更改 API,請告訴我。 如果我能弄清楚 API 部分,我會更新答案。

您無法直接使用this.objectsListOptionsForStep2從子組件(在本例中為FormChoiceTwo )訪問父組件的狀態(在本例中為WizardMainForm )。 你必須通過道具將它傳遞給一個孩子,所以這樣的事情應該可以工作:

  1. 在您的mainForm.js文件中,將您需要的數據作為道具值傳遞給FormChoiceTwo組件。 例如:
<FormChoiceTwo
  nextStep={this.nextStep}
  prevStep={this.prevStep}
  values={values}
  handleUserDetails={this.handleUserDetails} 
  handleChange={this.handleChange}
  objectsListOptionsForStep2={objectsListOptionsForStep2}
/>
  1. FormChoiceTwo內部通過this.props訪問它。 例子:
<select>
  {this.props.objectsListOptionsForStep2.map((u) => (
    <option>{u.id}</option>
  ))}
</select>

您還可以在FormChoiceTwo使用解構,例如const { objectsListOptionsForStep2 } = this.props; 然后你可以在 select 中刪除 this.props 並只寫objectsListOptionsForStep2.map

暫無
暫無

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

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