首页 > 解决方案 > 从下拉列表中选择一个选项会导致反应应用程序崩溃

问题描述

我有一个反应组件,它是一个从状态填充的选择/选项。当应用程序第一次呈现时,下拉列表会正确填充,但是当我选择其中一个选项时应用程序崩溃并且我收到错误“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 });
  };

标签: javascriptreactjs

解决方案


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

添加handleChange功能代码后编辑

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

像这样的东西可以工作

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

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


推荐阅读