2

I have a parent component which chooses the view to render according to a state in useReducer called state.viewOption.

The child component which dispatches it is something like:

export default function SearchFilter({ placeholder, onSearch }) {

    const [state, dispatch] = useReducer(
        collectionListReducer,
        initialCollectionState
    );

const option = state.viewOption;
  
    const handleChange = e => dispatch(setSketchesTrendsOption(e.target.value));

    return (
 <Grid container>
            <Grid item className={classes.selector}>
                <TextField
                    select
                    id="sketches-trends-selector"
                    value={option}
                    onChange={handleChange}
                >
                    <MenuItem value="Sketches">{t('TR_SKETCHES')}</MenuItem>
                    <MenuItem value="Trends">{t('TR_TRENDS')}</MenuItem>
                </TextField>
            </Grid>
   );
}

Then the parent component where I want to choose the view option according to this state is something like:

export default function CollectionListOption() {
    const [state, dispatch] = useReducer(
        collectionListReducer,
        initialCollectionState
    );

const viewOption = state.viewOption;

 useEffect(() => {

        console.log('view option in useEffect', viewOption);

    }, [viewOption]);


    switch (viewOption) {
        case 'Sketches':
            return <SketchesList />;
        case 'Trends':
            return <TrendsList />;
        default:
            return <SketchesList />;
    }
}

The thing is that I want to re-rerender this component <CollectionListOption/> once state.viewOption has changed it's value to show the right view. But I don't know why It only renders a console log when mounting and when I trigger the dispatch in <SearchFilter/> state changes in<SearchFilter/>but my state in<CollectionListOption/>doesn't notice and useEffect is not triggered.

Thank you!

pepinillo6969
  • 423
  • 6
  • 15
  • 1
    Your state isn't shared across the two components. Sounds like you may need some react shared state solution. Which one is best for you probably depends on what your app really needs to do. From what you show here, I might just choose a custom context. – Chris Farmer Aug 19 '21 at 18:32
  • 1
    @ChrisFarmer you are right! I thought you can get the state updates from another component with useReducer hook but I defenitely needed to use a context provider for that then they share exactly the same state. Thank you! – pepinillo6969 Aug 20 '21 at 16:08

1 Answers1

4

Thanks to @ChrisFarmer comment, this is how I solved it:

added a new component called CollectionStateProvider:

const CollectionStateContext = createContext();
    
    export default function CollectionStateProvider({ children }) {
        const [state, dispatch] = useReducer(
            collectionListReducer,
            initialCollectionState
        );
        return (
            <CollectionStateContext.Provider value={[state, dispatch]}>
                {children}
            </CollectionStateContext.Provider>
        );
    }
    
    export const useCollectionState = () => useContext(CollectionStateContext);

And then, in both components, instead of importing useReducer, I imported the useCollectionState as:

const [state, dispatch] = useCollectionState();
pepinillo6969
  • 423
  • 6
  • 15