Search code examples
htmlreactjstypescriptselecttypes

Issues with Displaying and Persisting Values in Select Component


I've written a component that represents a select with a set of options. Options are pulled from an object. The idea is that instead of 0, I want to display a cross (\u{274C}), and I also want to be able to revert to an empty field. It's important to me that the empty field does not have an integer value. I save an object with a key-value pair in localStorage and check what data ends up there. In general, I've found 2 problems that I don't quite understand how to solve: 1) When I choose 0, the cross is not displayed. 2) If I choose 0 and then try to return to an empty value, I see that 0 remains in localStorage. I don't need 0 there. Any ideas on what I'm missing?"

const SelectField: React.FC<SelectFieldProps> = ({diceOptions, onOptionChange, selectedOptions}) => {
return(
    <div className={Style.container}>
        {diceOptions.map((diceOption: DiceType, index: number) => {
            return (
                <select
                    key={`${diceOption.id}-${index}`}
                    className={Style.select}
                    onChange={(e) => {
                        const value = e.target.value === "" ? "" : Number(e.target.value);
                        onOptionChange(diceOption.id, value);
                    }}
                    value={selectedOptions[diceOption.id][0] || ""}
                >
                    {diceOption.values.map((value: number | "", index: number) => {
                        return (
                            <option key={index} value={value === 0 ? "0" : value}>
                                {value === 0 ? "\u{274C}": value}
                            </option>
                        )
                    })}
                </select>
            )
        })}
    </div>
)
}

Options are pulled from an object.

const diceOptions: Array<DiceType> = [
{id: 'One', values: ['', 0, 1, 2, 3, 4, 5]},
{id: 'Two', values: ['', 0, 2, 4, 6, 8, 10]},
{id: 'Three', values: ['', 0, 3, 6, 9, 12, 15]},
{id: 'Four', values: ['', 0, 4, 8, 12, 16, 20]},
{id: 'Five', values: ['', 0, 5, 10, 15, 20, 25]},
{id: 'Six', values: ['', 0, 6, 12, 18, 24, 30]}
];

Types:

export type DiceType = {
id: string,
values: Values[];
}

export type SelectFieldProps = {
diceOptions: DiceType[];
onOptionChange: (id: string, value: number | '') => void;
selectedOptions: {[key: string]: (number | '')[]};
}

export type StateType = Record<string, (number | '')[]>;
export type ActionType = { type: 'clear' | 'replace', id?: string, value?: number | '' };
const App: React.FC = () => {
const [state, dispatch] = useReducer(optionReducer, initialState);

const handleSelectChange = (id: string, value: number | ''):void => {
    dispatch({type: 'replace', id, value });
}

return (
    <>
        <SelectField diceOptions={diceOptions} onOptionChange={handleSelectChange} selectedOptions={state}/>
        <button onClick={() => clearLocalStorage(dispatch)}>Clear storage</button>
    </>


)
}

Solution

  • So the problem was with this line:

    value={selectedOptions[diceOption.id][0] || ""}
    

    Whenever my first element is null, undefined, 0, false (and 0 is just my case) it shows an empty string.