'How to get single value in react-select dropdown

I am trying to create a multi-select dropdown indicator (the second element shown here) using react-select.

The purpose is to show all blog post categories on a blog page, and then to only render the blog posts that are selected in the dropdown indicator.

The tags are extracted from their posts based on a GraphQL query and stored in useState variables "tags" and "renderedPosts".

How do I simply get a value from the dropdown when a category is added or removed? Reading the react-select API, I get this:

getValue () => ReadonlyArray<...>

I don't know how to use that, VS Code simply screams when I try add an arrow function as an attribute in the Select.

I understand there is supposed to be a "value" by default on the Select but if I try to use it I get undefined.

I don't know if mapping to the default value is a problem or if it has anything to do with the ContextProvider (which was necessary). There are other attributes I cannot get to work either, like maxMenuHeight (which is supposed to take a number).

Allow me to share my code (you can probably ignore the useEffect):

export default function Blog({ data }) {
    const { posts } = data.blog

    const [tags, setTags] = useState([])
    const [renderedPosts, setRenderedPosts] = useState([])

    // Context necessary to render default options in react-select
    const TagsContext = createContext();

    // setting all tags (for dropdown-indicator) and rendered posts below the dropdown (initially these two will be the same)
    useEffect(() => {
        const arr = [];
        data.blog.posts.map(post => {
            post.frontmatter.tags.map(tag => {
                if (!arr.some(index => index.value === tag)) {
                    arr.push({ value: tag, label: tag })
                }
            })
        });
        setTags([arr]);
        setRenderedPosts([arr]);
    }, []);

    function changeRenderedPosts(value???){
        setRenderedPosts(value???)
    }

    return (
        <Layout>
            <div>
                <h1>My blog posts</h1>
                <TagsContext.Provider value={{ tags }}>
                    <Select
                        defaultValue={tags.map(tag => tag) }
                        isMulti
                        name="tags"
                        options={tags}
                        className="basic-multi-select"
                        classNamePrefix="select"
                        // HOW DO I PASS THE VALUE OF THE ADDED/DELETED OPTION?
                        onChange={() => changeRenderedPosts(value???)}
                        maxMenuHeight= {1}
                    />
                </TagsContext.Provider>
                // posts to be rendered based on renderedPosts value
                {posts.map(post => {

EDIT: The closest I have now come to a solution is the following:

   function changeRenderedTags(options){
        console.log(options) //logs the remaining options
        setRenderedTags(options) //blocks the change of the dropdown elements
    }

    return (
        <Layout>
            <div>
                <h1>My blog posts</h1>
                <TagsContext.Provider value={{ tags }}>
                    <Select
                      ...
                        onChange={(tagOptions) => changeRenderedTags(tagOptions)}
             

I click to delete one option from the dropdown and I get the other two options in "tagOptions". But then if I try to change "renderedTags", the update of the state is blocked. I find this inexplicable as "setRenderedTags" has nothing to do with the rendering of the dropdown or its data!



Solution 1:[1]

with isMulti option true, you get array of options(here it's tags) from onChange callback. so I guess you could just set new tags and render filtered posts depending on the selected tags like below?


const renderedPosts = posts.filter(post => post.tags.some(tag => tags.includes(tag)))

...
onChange={selectedTags => {
  setTags(selectedTags ? selectedTags.map(option => option.value) : [])
}}
...

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1