【问题标题】:Selecting an option from a dropdown list causes react app to crash从下拉列表中选择一个选项会导致反应应用程序崩溃
【发布时间】:2021-09-20 01:30:03
【问题描述】:

我有一个反应组件,它是一个从状态填充的选择/选项。当应用程序第一次呈现时,下拉列表会正确填充,但是当我选择其中一个选项时,应用程序崩溃并且我收到错误“values.appOwner.map() 不是函数。我正在寻找填充此表单并将其发送到我的后端服务器。我想将选定的公司传递到后端。这是我的代码。

import React from 'react';
import Link from 'next/link';
import { useRouter } from 'next/router';

import { Image, Button, Badge } from 'antd';

const MobileAppCreateForm = ({
  handleSubmit,
  handleImage,
  handleChange,
  values,
  preview,
  uploadButtonText,
  handleImageRemove
}) => {
  const router = useRouter();

  return (
    <form className='add-content-form' onSubmit={handleSubmit}>
      <div class='input-group'>
        <input
          type='text'
          className='form-control'
          placeholder='Mobile App Name'
          name='appName'
          value={values.appName}
          onChange={handleChange}
          style={{ marginRight: '.5rem' }}
        />
        <select
          title='Select Corporation'
          name='appOwner'
          className='form-select'
          value={values.appOwner}
          onChange={handleChange}
        >
          <option selected>Select a Corporation</option>
          {values.appOwner &&
            values.appOwner.map(corp => (
              <option key={corp.corporationId} value={corp.corporationName}>
                {corp.corporationName}
              </option>
            ))}
        </select>
        <span
          class='input-group-text ant-btn-primary'
          style={{ cursor: 'pointer' }}
          onClick={e => router.push('/add_content/add_corporation')}
        >
          Add Corporation
        </span>
      </div>
      <div className='mb-3 mt-3'>
        <textarea
          className='form-control'
          rows='4'
          placeholder='Enter Mobile App Description'
          name='appDescription'
          value={values.appDescription}
          onChange={handleChange}
        />
      </div>
      <div className='row'>
        <div className='col-md-6'>
          <input
            type='text'
            className='form-control'
            placeholder='Mobile App Website'
            name='appWebsite'
            value={values.appWebsite}
            onChange={handleChange}
          />
        </div>
        <div className='col-md-6'>
          <input
            type='text'
            className='form-control'
            placeholder='Mobile App Privacy Policy Link'
            name='appPrivacyPolicyLink'
            value={values.appPrivacyPolicyLink}
            onChange={handleChange}
          />
        </div>
      </div>
      <div className='row mt-3'>
        <div className='col-md-4'>
          <select
            className='form-select'
            name='appUserAccountDownload'
            onChange={handleChange}
            value={values.appUserAccountDownload}
          >
            <option selected disabled>
              User Account Download
            </option>
            <option value='true'>True</option>
            <option value='false'>False</option>
          </select>
        </div>
        <div className='col-md-4'>
          <select
            className='form-select'
            onChange={handleChange}
            name='appLocationHistory'
            value={values.appLocationHistory}
          >
            <option selected disabled>
              User Location History
            </option>
            <option value='true'>True</option>
            <option value='false'>False</option>
          </select>
        </div>
        <div className='col-md-4'>
          <input
            type='text'
            className='form-control'
            placeholder='Mobile App Data Retention Length'
            name='appDataRetention'
            value={values.appDataRetention}
            onChange={handleChange}
          />
        </div>
      </div>
      <div className='row mt-3'>
        <div className='col-md-12'>
          <div className='form-group d-grid gap-2'>
            <label className='btn btn-outline-secondary btn-block text-start'>
              {uploadButtonText}
              <input
                type='file'
                name='image'
                onChange={handleImage}
                accept='image/*'
                hidden
              />
            </label>
            {preview && (
              <div style={{ position: 'relative' }}>
                <Badge
                  count='X'
                  onClick={handleImageRemove}
                  style={{
                    cursor: 'pointer',
                    position: 'absolute',
                    top: '5px',
                    right: '2px'
                  }}
                >
                  <Image width={200} src={preview} />
                </Badge>
              </div>
            )}
          </div>
        </div>
      </div>
      <div className='mb-3 mt-3'>
        <textarea
          className='form-control'
          rows='4'
          placeholder='iOS Associated Files'
          name='appIosAssociatedFiles'
          value={values.appIosAssociatedFiles}
          onChange={handleChange}
        />
      </div>
      <div className='mb-3 mt-3'>
        <textarea
          className='form-control'
          rows='4'
          placeholder='iOS Associated Files'
          name='appAndroidAssociatedFiles'
          value={values.appAndoridAssociatedFiles}
          onChange={handleChange}
        />
      </div>
      <Button
        type='submit'
        className='btn btn-primary ant-btn-primary'
        onClick={handleSubmit}
        disabled={values.loading || values.uploading}
        loading={values.loading}
        shape='round'
      >
        {values.loading ? 'Saving...' : 'Save'}
      </Button>

      <Button
        type='submit'
        className='btn btn-primary ant-btn-primary'
        disabled={values.loading || values.uploading}
        loading={values.loading}
        shape='round'
        style={{ marginLeft: '.25rem' }}
      >
        {values.loading ? 'Publishing...' : 'Publish'}
      </Button>
    </form>
  );
};

export default MobileAppCreateForm;

这是我的 handleChange 方法:

const handleChange = (e, index) => {
    setValues({ ...values, [e.target.name]: e.target.value });
  };

【问题讨论】:

  • 您将选择绑定到 values.appOwner,这让我认为它是一个对象,而不是一个数组。地图用于数组。

标签: javascript reactjs


【解决方案1】:

看来values.appOwner 不是一个数组,所以你不能在上面调用map()。您可以检查 appOwner 是否实际上是数组,而不是仅检查它是否真实 ({values.appOwner &amp;&amp; ...),因为此条件会传递一个简单的字符串或数字,然后在调用 map 时会崩溃。您可以使用Array.isArray() 来代替。您仍然应该尝试调试并查看 values.appOwner 的实际值是什么,以了解为什么没有返回数组。

添加handleChange功能代码后编辑

问题在于handleChange 方法以及您处理状态的方式。您应该使用不同的对象来存储选择的值和选择的初始选项。如果您查看您的代码,您将使用 values.appOwner 既作为 select 标记中的 value 属性,又作为一个数组来迭代以构建选项。一旦选择了一个选项,您将使用所选值更新appOwner,使其不再是一个数组。

这样的东西可以工作

 const [corporation, setCorporation] = useState('');
 ....
   <select
      title='Select Corporation'
      name='appOwner'
      className='form-select'
      value={corporation}
      onChange={event => setCorporation(event.target.value)}

您可能希望将选定的公司存储在父组件中,但这里重要的是它与 values.appOwner 部分分开

【讨论】:

  • Rodrigo Array.isArray() 的结果返回 true。它是一个对象数组。它在加载时正确呈现。只有当我从列表中选择一个项目时它才会崩溃。
  • 这表明问题实际上出在handleChange 方法上。它有什么作用?它可能会以不正确的方式更改 value 属性。
  • 谢谢罗德里戈。它在我的 handleChange 方法中的某个地方。我将其添加到我的原始帖子中以供评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-22
  • 2017-05-28
  • 2016-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多