Muteman30
Muteman30

Reputation: 23

Props in child doesn't update when parent updates it's state

I've spent a few days on this and it is driving me crazy now.

I have a state in a parent component containing an Array[string] of selected squares which is passed to the child component (a map) along with the set function from the hook. The issue is that when I set the new squares they are changed in the parent, but on selection of another square it is not taking into account the already selected squares.

function Parent(props){
    const [selectedSquares, setSquares] = useState([]);
    
    useEffect(() => {
        console.log('parent useEffect', selectedSquares);
    }, [selectedSquares]);
    
    return (
        <Child selectedSquares={selectedSquares}
               handleSquaresChange={setSquares}
        />
    )
}

function Child(props){
   const {selectedSquares, handleSquaresChange} = props;

    useEffect(() => {
        console.log('child useEffect', selectedSquares)
    }, [selectedSquares]);

    const handleSelect =  evt => {
        if(evt.target){
           const features = evt.target.getFeatures().getArray();
           let selectedFeature = features.length ? features[0] : null;
           if (selectedFeature) {
               console.log('select (preadd):', selectedSquares);
               const newTile = selectedFeature.get('TILE_NAME');
               const newSquares = [...selectedSquares];
               newSquares.push(newTile);
               const newTest = 'newTest';
               handleSquaresChange(newSquares);
               console.log('select (postadd):', newSquares);
        }
    }
    
    return(
        <Map>
            <Select onSelect={handleSelect}/>
        </Map>
    )
}

On the first interactionSelect component I get this output from the console:

parent useEffect: [],

child useEffect: [],

select (preadd):[],

child useEffect:['NX'],

parent useEffect: ['NX'],

select (postadd): ['NX'].

Making the second selection this is added to the console:

select (preadd):[],

select (postadd): ['SZ'],

child useEffect:['SZ'],

parent useEffect: ['SZ'].

Upvotes: 0

Views: 61

Answers (2)

Muteman30
Muteman30

Reputation: 23

Turns out there is an addEventListener in the library I am using that is going wrong. Thanks to everyone who responded but turns out the issue was not with React or the state stuff.

Upvotes: 1

jolo
jolo

Reputation: 660

Consider something like the code below. Your parent has an array with all your options. For each option, you render a child component. The child component handles the activity of its own state.

function Parent(props){
    // array of options (currently an array of strings, but this can be your squares)
    const allOptions = ['opt 1', 'opt 2', 'opt 3', 'etc']; 
     
    return (
        <>
            // map over the options and pass option to child component
            {allOptions.map((option) => <Child option={option}/>)} 
        </>
    )
}

function Child({ option }){
    const [selected, setSelected] = useState(false); // default state is false
     
    return (
        <>
            // render option value
            <p>{option}</p> 
            // shows the state as selected or not selected
            <p>Option is: {selected ? "selected" : "not selected"}</p> 
            // this button toggles the active state
            <button onClick={() => setSelected(!selected)}>Toggle</button>
        </>
    )
}

Upvotes: 0

Related Questions