user101289
user101289

Reputation: 10422

props value initially populated, then isn't in react js

I've got a simple component I'm trying to build-- a multiselect with a user's current security levels pre-selected. The initial security level props are being passed to the component as expected. I then go out to a webservice and grab all available security levels, and match up the props security level array (which is just an array of short codes) with the label of the security level from the service.

The problem is that in the parseResults method the security_levels prop shows as an empty array [] when it's fine a few lines before-- how is this happening? I don't understand why the props are populated at one stage, and then they're not.

import React, { useState, useEffect } from 'react';
import Loader from "react-loader-spinner";
import QueryHelper from "../Utilities/QueryHelper";
import Select from "react-select";

function SecurityLevelSelect({security_levels, onSecurityLevelChange}) {
    console.log("outside parseResults");
    console.log(security_levels); // shows expected array of props.security_level shortCode values

    const [selectedItems, setSelectedItems] = useState([]);
    const [items, setItems] = useState([])
    const [error, setError] = useState(null);
    const [isLoaded, setIsLoaded] = useState(false);

    const helper = new QueryHelper();

    const handleChange = (e) => {
        onSecurityLevelChange(e.target.value);
    }

    useEffect(() => {
        fetchData();
    }, [])

    const fetchData = () => {
        setIsLoaded(false);

        helper.fetchData('securitylevel')
            .then(
                (result) => {
                    setIsLoaded(true);
                    setItems(parseResults(result.results));
                },
                (error) => {
                    setIsLoaded(true);
                    setError(error);
                }
            )
    }

    const parseResults = (results) => {
        let data = [];
        let selected = [];

        console.log("inside parseResults");
        console.log(security_levels); // shows [] as value of security_levels

        results.forEach(result => {
            console.log(result.shortCode);
            let datum = {
                value: result.shortCode,
                label: result.name
            }

            if (security_levels.includes(result.shortCode)) {
                console.log(result.shortCode + ' is selected');
                selected.push(datum)
            }
            data.push(datum)
        });

        setSelectedItems(selected); // sets it to []
        return data;
    }

    // then render some stuff
    return (
        <some_random_content />
    ); 
}

export default SecurityLevelSelect;

Upvotes: 0

Views: 33

Answers (1)

Harley Lang
Harley Lang

Reputation: 2333

I think the reasons for security_levels being available within your component but not parseResults can be due to either rendering or scoping.

With useEffect, it may be that security_levels is not available on its first render, but it doesn't know to run again. So perhaps try:

    useEffect(() => {
        fetchData();
    }, [security_levels])      {/* <----- add security_levels as a dependency here */}

You might have to consider passing the security_level to fetchData() and then to parseResults which would resolve the issue of scoping.

Upvotes: 1

Related Questions