How do I refresh a component's select items when the items are changed in another component?

Viewed 143

I have a screen that looks like this: Screen

The Home component is somewhat like below (just for illustration):

function Home()
{
  return (
    <GridContainer> 
          <Grid> <LeftPanel> </Grid> 
          <Grid><RightPanel></Grid>
    </GridContainer>
  );
}

My LeftPanel component is somewhat like below (just for illustration):

function LeftPanel()
{
  const [items, setItems] = useState([]);

  const getItemList = async() {
    setItems(  callRestMethod(url)  );
  }  

  useEffect(() => {
    (async () => {
      await getItemList();
    })();    
  });
  
  return (
    <Select> 
          {items.map( (item) => <MenuItem key={item} value={item}> item </MenuItem>)}
    </Select>
  );
}

How do I update the Select list items in Left Panel component when I add or delete an item from the RightPanel component?

1 Answers

I used react-redux and thunk

here is the react-redux Example, and below is the full code

import "./styles.css";
import React, { useEffect, useState } from "react";
import { createStore, applyMiddleware, compose } from "redux";
import { Provider, useDispatch, useSelector } from "react-redux";
import thunk from "redux-thunk";
import axios from "axios";

//REMOVE "Ahmad Rahmani" IF YOU DONT HAVE INITIAL DATA.
const initialState = {
  data: ["Ahmad Rahmani"]
};
//REDUCERS
export const MyReducer = (state = initialState, action) => {
  switch (action.type) {
    case "FETCH_ALL":
      //REMOVE initialState.data IF YOU DONT HAVE INITIAL DATA.
      return { ...state, data: [initialState.data, ...action.payload.data] };

    case "ADD":
      return { ...state, data: [...state.data, action.payload.item] };
    default:
      return state;
  }
};
//
//ACTIONS
export function addAction(item) {
  return (dispatch) => {
    //MAYBE YOU WANT TO SAVE IT IN DATABASE
    //SO YOU SHOULD CALL AN API
    //BUT NOW I DON'T
    dispatch({
      type: "ADD",
      payload: { item: item }
    });
  };
}
export function fetchAction() {
  return (dispatch) => {
    axios.get("https://jsonplaceholder.typicode.com/users").then((response) => {
      dispatch({
        type: "FETCH_ALL",
        payload: { data: response.data.map((m) => m.name) }
      });
    });
  };
}
//

export default function App() {
  const enhancers = [applyMiddleware(thunk)];
  const store = createStore(MyReducer, compose(...enhancers));
  return (
    <Provider store={store}>
      <div className="App">
        <LeftPanel />
        <RightPanel />
      </div>
    </Provider>
  );
}
export const LeftPanel = () => {
  const { data } = useSelector((state) => state);
  const dispatch = useDispatch();
  useEffect(() => {
    dispatch(fetchAction());
  }, []);
  return (
    <div className="left-panel">
      <select>
        {data.map((item) => (
          <option value={item}>{item}</option>
        ))}
      </select>
    </div>
  );
};
export const RightPanel = () => {
  const dispatch = useDispatch();
  const [text, setText] = useState("");
  const { data } = useSelector((state) => state);
  useEffect(() => {
    dispatch(fetchAction());
  }, []);
  const handleClick = (event) => {
    event.preventDefault();
    if (text === "") return;
    dispatch(addAction(text));
    setText("");
  };
  const handleChange = (event) => {
    setText(event.target.value);
  };
  return (
    <div className="right-panel">
      <input type="text" value={text} onChange={handleChange} />
      <button onClick={handleClick}>add Item</button>
      <select>
        {data.map((item) => (
          <option value={item}>{item}</option>
        ))}
      </select>
    </div>
  );
};
Related