OnChangePoll не является функцией в компоненте флажка - PullRequest
0 голосов
/ 28 мая 2019

У меня есть список флажков, которые получают функцию обработчика, которая изменяет состояние, когда флажок установлен / снят. Когда я нажимаю на флажок, я получаю следующую ошибку:

TypeError: onChangePoll is not a function

Я пробовал:

  • Изменение функции обработчика на функцию стрелки
  • Перемещение компонента-флажка из его модульного файла, чтобы поместить его в файл, где находится функция
  • Изменено onChange на onClick
  • Проследил это через DOM, поскольку это отрисовывает

Похоже, что функция обработчика правильно передается компоненту при рендеринге, но когда я делаю щелчок, она исчезает.

Для приведенного ниже кода affiliates - это массив, который выглядит следующим образом:

[
    {
        shortName: `a`
    },
    {
        shortName: `b`
    },
    {
        shortName: `c`
    }
];

NewPoll.js

import React, { useState } from 'react';
import { Redirect } from "react-router";
import { AffiliateSelects } from './../helpers/FormElements';
import { affiliates } from './../helpers/Config';
import { initialNewPoll } from './../helpers/Config';
import { isAffiliates, validateNewPollModal } from './../helpers/FormValidator';

function NewPoll(props) {

  const {
    pollData,
    type,
    onChangePoll
  } = props;

  // Set headline for modal
  const headline = type === `new` ? `Add a New Poll` : `Edit “${pollData.pollName.value}”`;

  return(
    <div className="modal-content">
      <h2>{headline}</h2>
      <form className="form__inputs form__inputs--modal">
        <div className="form__inputs-row">
          <label
            className={pollData.affiliates.error ? `form__input-label form__input-label--error` : `form__input-label`}
            htmlFor="affiliates"
          >
            {pollData.affiliates.error ? `Affiliates (${pollData.affiliates.error})` : `Affiliates`}
          </label>
          <AffiliateSelects
            type="checkbox"
            name="affiliates"
            state={pollData.affiliates.value}
            onChangePoll={onChangePoll}
          />
        </div>
        <div className="form__buttons-row">
          <ul className="form__buttons-row-list">
            <li className="form__buttons-row-item">
              <button
                className="button"
                type="reset"
                name="clear-filters"
                onClick={(e) => onChangePoll({
                  name: `clearFields`
                })}
              >
                Clear Fields
              </button>
            </li>
            <li className="form__buttons-row-item">
              <button
                className="button"
                type="reset"
                name="create-poll"
                onClick={(e) => onChangePoll({
                  name: `createPoll`
                })}
              >
                {type === `new` ? `Create Poll` : `Save Edits`}
              </button>
            </li>
          </ul>
        </div>
      </form>
    </div>
  )
}

export const NewPollModal = (props) => {

  const {
    pollData,
    setPollData,
    type
  } = props;

  const onChangePoll = (el) => {
    // Validate the poll data being sent through
    let validPoll;
    switch(el.name) {
      case `affiliates`:
        validPoll = isAffiliates(el.value, pollData.affiliates.value);
        break;
      case `clearFields`:
        validPoll = initialNewPoll;
        break;
      default:
        break;
    }
    if (el.name === `createPoll`) {
      // Check to make sure all of the fields are valid
      const isPollValid = validateNewPollModal(pollData);
      if (isPollValid.valid) {
        // If they are valid, send the state to the poll edit page
        setPollData({
          ...pollData,
          valid: true
        });
      } else {
        // If they are not valid, create errors on the form
        setPollData(isPollValid.validPoll);
      }
    } else if (el.name === `clearFields`) {
      setPollData(validPoll);
    } else {
      setPollData({
        ...pollData,
        [`${el.name}`]: {
          valid: validPoll.valid,
          error: validPoll.error,
          value: validPoll.value
        }
      });        
    }
  }

  if (pollData.valid) {
    return(
      <Redirect
        to={{
          pathname: "/poll",
          state: {
            affiliates: pollData.affiliates.value
          }
        }}
      />
    )
  } else {
    return(
      <NewPoll
        pollData={pollData}
        type={type}
        onChangePoll={onChangePoll}
      />
    )         
  }

}

FormElements.js

import React from 'react';
import { affiliates } from './Config';

function ListItem(props) {
  const {
    aff,
    type,
    state,
    onChangePoll
  } = props;

  // If we are in edit mode, add the checkmark if the affiliate is in state
  const checked = state.includes(aff) ? true : false;
  const affiliates = {
    name: `affiliates`,
    value: aff
  };

  if (type === `checkbox`) {
    console.log(onChangePoll);
    return(
      <li className="affiliate-selects__items">
        <input
          className="affiliate-selects__checkbox"
          type={type}
          name="affiliates"
          id={`affiliates-${aff}`}
          checked={checked}
          onChange={() => onChangePoll(affiliates)}
        />
        <label className="affiliate-selects__label" htmlFor={`affiliates-${aff}`}>{aff}</label>
      </li>
    )
  } else if (type === `list`) {
    return(
      <li className="affiliate-selects__items">{aff}</li>
    )
  }
}

function List(props) {

  const {
    type,
    state,
    affList,
    onChangePoll
  } = props;

  let listClass;
  if (type === `checkbox`) {
    listClass = `affiliate-selects affiliate-selects--checkbox`;
  } else if (type === `list`) {
    listClass = `affiliate-selects affiliate-selects--list`;
  }

  return(
    <ul className={listClass}>
    {affList.map((aff) =>
      <ListItem
        key={`affiliate-selects-${aff.shortName}`}
        aff={aff.shortName}
        type={type}
        state={state}
        onChangePoll={onChangePoll}
      />
    )}
    </ul>
  )
}

/**
 * Displays a list of affiliates, eiter as a checkbox list, or as a regular list.
 * @param {String}    props.type            Will display the affiliates as a list of checkboxes for a display  *                                                  list
 *                                          Ex: `checkbox` || `list`
 * @param {Function}  props.handleOnChange  Event handler function that changes the items that are filtered
 *                                          (optional)
 * @param {String}    props.prefix          Will prefix all input IDs so form inputs will work correctly
 *                                          (optional)
 * @param {Array}     props.affArray        Array of affiliate string names
 *                                          Ex: [`nj`, `oregonlive`, `masslive`]
 *                                          (optional)
 */
export function AffiliateSelects(props) {

  const type = props.type || `list`;
  const state = props.state || [];
  const {
    affArray,
    onChangePoll
  } = props;

  // If the user doens't pass in an array, list all of the affiliates from the config
  let affList;
  if (affArray === undefined || affArray.length === 0) {
    affList = affiliates;
  } else {
    affList = affArray.reduce((accum, aff) => {
      accum.push({shortName: aff});
      return accum;
    }, []);
  }

  return(
    <List
      type={type}
      state={state}
      affList={affList}
      onChangePoll={onChangePoll}
    />
  )

}

Ожидаемое поведение: пользователь нажимает флажок рядом с партнером, и этот партнер проверяется обработчиком и сохраняется в состоянии.

...