У меня есть список флажков, которые получают функцию обработчика, которая изменяет состояние, когда флажок установлен / снят. Когда я нажимаю на флажок, я получаю следующую ошибку:
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}
/>
)
}
Ожидаемое поведение: пользователь нажимает флажок рядом с партнером, и этот партнер проверяется обработчиком и сохраняется в состоянии.