import React, {useRef, useState} from 'react'; // A list of text fields for a crop's names, numbered the way the controller // reads them (`field`[1], `field`[2], ...), with a button to add another and // one on each row to remove it. There is always at least one field, so emptying // it and saving clears the crop's names. // // `renderInput({id, name, value, onChange})` draws a field, so a list can use // a plain input or one that suggests names. `buttonClass` is the stem of the // buttons' class names (`add--row`, `remove--row`). export default function NameFields({names, field, noun, buttonClass, help, renderInput}) { const nextKey = useRef(0); const newRow = (value) => ({key: nextKey.current++, value: value ?? ''}); // a new crop's blank name is null const [rows, setRows] = useState(() => (names.length ? names : ['']).map(newRow)); const change = (key, value) => setRows(rows.map((row) => (row.key === key ? {...row, value} : row))); const remove = (key) => setRows(rows.filter((row) => row.key !== key)); return (
{rows.map((row, index) => { const number = index + 1; const id = `${field}[${number}]`; return (
{renderInput({id, name: id, value: row.value, onChange: (value) => change(row.key, value)})}
); })} {help}
); }