reactjsreact-selectreact-final-form

How to format value of the React Select


I use "react final forms" and "react select".

I've organized an interface and functionality works, but I have one thing which I don't like.

React select requires options in next format:

const options = [
  { value: 'chocolate', label: 'Chocolate' },
  { value: 'strawberry', label: 'Strawberry' },
  { value: 'vanilla', label: 'Vanilla' }
]

and the value also should be set as { value: 'chocolate', label: 'Chocolate' }.

But for me is strange to have in my model of data (and send to the server also) the value like this - { value: 'chocolate', label: 'Chocolate' }, because I need only 'chocolate'.

Easy way is format the object into a single value after the form will be saved and format back from single value to the object before the rendering of the element. I know how to do it outside of form, but in this case I should solve this problem again and again for each select element separately.

What I would like to do:

  1. Find a way how to set value of the react select as single value, like 'chocolate' instead of object.

OR

  1. Create a wrapper for react select component and format value there when it sets (it's easy) and when the form get the value from this field (this I don't know how to do).

I will appreciate any help.


Solution

  • Method 1

    With strings:

    import React, { useState } from "react";
    import ReactDOM from "react-dom";
    import Select from "react-select";
    
    const data = ["1", "2"];
    
    function SingleStringReactSelect() { 
      const [option, setOption] = useState();
      return (
        <section>
          <Select 
            onChange={option => setOption(option)}
            value={[option]}
            getOptionLabel={label => label}
            getOptionValue={value => value}
            closeMenuOSelect={false}
            options={data}
          />
        </section>
      );
    }
    

    Method 2:

    Created example: https://codesandbox.io/s/react-codesandboxer-example-z57ke

    You can use map in options and with Wrapper like SingleValueReactSelect

    import React, { Fragment, useState } from "react";
    import Select from "react-select";
    
    const data = ["chocolate", "strawberry", "vanilla"];
    
    export function SingleValueReactSelect(props) {
      const [selectedItem, setSelectedItem] = useState();
      return (
        <Select
          {...props}
          value={selectedItem}
          onChange={item => {
            setSelectedItem(item);
            props.onChange(item.value);
          }}
          options={props.options.map(item => ({ label: item, value: item }))}
        />
      );
    }
    
    export default function AppDemo() {
      return (
        <Fragment>
          <p>SingleValueReactSelect Demo</p>
          <SingleValueReactSelect
            isClearable
            isSearchable
            options={data}
            onChange={item => {
              alert(item);
            }}
          />
        </Fragment>
      );
    }