React - Refreshing a component with the help of another component

I've created a NavBar component that contains a list of links generated dynamically. These links are fetched from the backend based on specific categories and are stored within a child component of NavBar named DrawerMenu.

The NavBar itself is a child component of the main App.js.

Within my Category component, there's a function to delete categories, and upon deletion, I want to remove the corresponding link from the NavBar. How can I achieve this?

Below are the details of the components:

DrawerMenu component

class DrawerMenu extends Component {
  state = {
    menuItems: [] // Contains objects like { name: "", link: "" }
  }

  getData = (query) => {
    // Fetch category data from the backend and store it in this.state.menuItems
  }

  componentDidMount() {
    this.getData(menuItemsQuery)
  }

  render() {
    const { classes, handleDrawerClose, open } = this.props
    const { menuItems } = this.state

    const drawer = (classes, handleDrawerClose) => (
      <div>
          ...

          {
            menuItems.map((menuItem, index) => (
              <Link color="inherit" key={index} to={menuItem.link} className={classes.drawerLink} component={RouterLink}>
                <ListItem button className={classes.drawerListItem} onClick={handleDrawerClose}>
                  <ListItemText primary={menuItem.name} />
                </ListItem>
              </Link>
            ))
          }
          
          ...
      </div>
    )
    
    ...

    return (
      <div>
        <Drawer
          variant="temporary"
          anchor='left'
          open={open}
          onClose={handleDrawerClose}
          classes={{
            paper: `${open ? classes.drawerOpen : null} ${!open ? classes.drawerClose : null}`,
          }}
          ModalProps={{
            keepMounted: true, // Better open performance on mobile.
          }}
        >
          {drawer(classes, handleDrawerClose)}
        </Drawer>
      </div>
    )
  }
}

NavBar component

function PrimarySearchAppBar(props) {
    return (
        <div className={classes.grow}>
            
            ...
            
            <DrawerMenu
                classes={classes}
                handleDrawerClose={handleDrawerClose}
                open={open}
            />
            
            ...
        </div>
    )
}

Category component

class Category extends Component {
    ...
    
    deleteCategory = async () => {
        // Backend request to delete category
        this.props.history.push(`/`)
    }
    
    ...
}

Answer №1

When it comes to managing state in your React application, there are two common approaches you can take: utilizing a state management tool like Redux, or simply passing the state down the component tree as props.

Redux is typically preferred when multiple components rely on the same state, or when the component needing access to the state is deeply nested within the tree. In these cases, passing the state down as props can become unwieldy.

Assuming that your component tree isn't overly complex, I will demonstrate a straightforward example of passing props down the tree in this case.

class DrawerMenu extends Component {
  // Here, we'll handle state management to facilitate deletion
  state = {
    menuItems: [] // Consisting of objects with keys 'name' and 'link'
  }

  handleDelete = (id) => {
    let updatedMenuItem = [...this.state.menuItems]; // Make a copy
    updatedMenuItem = updatedMenuItem.filter(item => item.id !== id); // Remove the deleted item
    this.setState({
       menuItems: updatedMenuItem
    })    
   
  }
  ...

   // When rendering the category component
   <Category handleDelete={handleDelete}/> // Pass a reference to the delete method

}


Category Component

 class Category extends Component {
    ...
    
    deleteCategory = async () => {
        // Backend request to delete category
        this.props.handleDelete(categoryId) // Pass the category id
        this.props.history.push(`/`)
    }
    
    ...
}

If you're new to state management, I recommend diving deeper into this key aspect of React. Understanding tools like Redux and the Context API will be crucial for your development journey.

Answer №2

It's puzzling why Dennis Vash decided to remove their answer, as it was accurate, although lacking in detail.

To properly delete a category, the backend shouldn't be called directly from within the category component. Instead, use a shared callback function in a common ancestor component that both the category component and the navbar have access to. This callback will handle deleting a category and then refreshing the list of categories from the server. In this scenario, the shared ancestor component is MyCategoriesProvider

Since the category component may exist in various locations within the app compared to the NavBar, utilizing context is recommended.

While incorporating Redux would be beneficial in this situation, I'll showcase a solution using Context without pushing for Redux implementation.

// code snippet

An edit has been made:

Noticing a mix of class and functional components, it's worth exploring this article on effectively utilizing the context api in both types of components - useContext hook for functional components and consumer for class components.

Answer №3

After completing the delete request, I would simply update the list of categories retrieved from the server.

My approach would be:

  • To make the drawer component less intelligent by passing it the list of menuItems.
<DrawerMenu
    classes={classes}
    handleDrawerClose={handleDrawerClose}
    open={open}
    items={/* ... */}
/>

This step is crucial because now, refreshing the rendered item list involves just passing a new list. This ensures that the server-side logic remains separate from this component.

  • If you are unsure where the Category components are rendered, and assuming they are outside the PrimarySearchAppBar, it seems like these menuItems need to be passed down from a higher level. Here are 2 solutions:

    1. I would fetch the menuItems from the same source as the categories:
const App = props => {
    const [categories, setCategories] = React.useState([])
    const [menuItems, setMenuItems] = React.useState([])

    const fetchCategories = useCallback(()=> {
        yourApi.getCategories().then(categories => setCategories(categories))
    })

    const fetchMenuItems = useCallback(() => {
        yourApi.getMenuItems().then(menuItems => setMenuItems(menuItems))
    })

    useEffect(() => {
        fetchCategories()
    }, [])

    useEffect(() => {
       fetchMenuItems()
    }, [categories])

    const handleDeleteCategory = useCallback(idToDelete => {
        yourApi.deleteCategory(idToDelete).then(fetchCategories)
    })

    return (
        <div>
             <PrimarySearchAppBar menuItems={menuItems}/>
             <Categories categories={categories} onDeleteClick={handleDeleteCategory} />
        </div>
    )

}
  1. You could achieve the same outcome using a provider and the content API if you prefer not to clutter this component with all the logic. It's advisable to have smart/fetches/server-side logic in a high-level component and then pass down props to simpler components.

PS. There's an efficient hook for simplifying fetch operations: https://github.com/doasync/use-promise

I currently utilize a customized version of a usePromise hook that I enhanced with some useful features. If you're interested, I can share it, but I don't want to overwhelm the answer with unnecessary details.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to locate the module model in sequelize

Having some trouble setting up a basic connection between Postgres and SQL using Sequelize. I keep getting an error where I can't require the model folder, even though in this tutorial he manages to require the model folder and add it to the sync, lik ...

Styling the active selection in nav class with bold attribute in Bootstrap/AngularJs

How can I apply the bold attribute to the currently selected nav bar item? <ul class="nav"> <li role="presentation" ng-repeate="item in items" ng-class="{'active':navLink == item.header}"> </li> &l ...

The jQuery pop-up fails to activate on the initial click

I have multiple "Buy Now" buttons for different products. If the button is labeled as "sold-out," it should not do anything, but if it's available, it should trigger a jQuery Magnific Popup. Currently, the popup only opens after the second click becau ...

"Encountered an issue with Next-Auth session returning as undefined in getServerSideProps using NextJS version 13.2

When inspecting the code below, session is found to be undefined upon logging from the client side after being transferred from getServerSideProps. import { getServerSession } from 'next-auth/next'; import { authOptions } from './api/auth/[. ...

problem encountered while attempting to transmit data to multer in React

I was attempting to upload an image to the backend using Multer. I have reviewed the backend code multiple times and it appears to be correct. Could there be an issue with my front-end code? Here is a POST code snippet: const response = await fetch(' ...

React JS - Breaking down the distinction between PublicTheme and PublicTheme

In my React project, I am currently working on creating the admin dashboard and designing the UI area for user interaction. I have encountered an issue where I am unable to separate the admin theme from the PublicTheme. Even when navigating to "/admin/lo ...

Error: The call stack has reached its maximum size while running an npm install

Attempting to execute npm install, encountered the following console output: npm ERR! Linux 4.8.0-27-generic npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "install" npm ERR! node v6.9.1 npm ERR! npm v3.10.8 npm ERR! Maximum call stack size exceeded npm ...

A step-by-step guide on accessing the data from an uploaded JSON file in a React application

One exciting feature is the drag and drop component that allows users to add multiple files. However, there seems to be an issue with displaying the content of a JSON file once it's added. Below is the code snippet in question: if (files?.length) ...

Leveraging Gatsbyjs to Integrate GraphQL Data with Material UI Library

Just starting out as a Frontend Developer and currently learning Gatsbyjs along with the Material UI library. I'm working on creating a new page using the Material UI Gatsby Starter code available here. However, I've encountered an issue when tr ...

Learn how to toggle the display of a div using jQuery, just like the functionality on the popular website

Visit Mashable here Below is the script I am currently using: $(document).ready(function(){ $(".show_hide5").mouseover(function(){ $('.selected').removeClass('selected'); $(this).next().fadeIn("slow").addClass(&apo ...

initiate file transfer

I am currently developing a web application using NextJS with TRPC. Within the app, there is a form that requires users to select a file. My goal is to pass this file through a TRPC call to handle all file-related logic on the backend rather than the front ...

Steps for avoiding rendering an attachment

Currently, I am utilizing botframework-webchat in a react application that is linked to a skillbot. Through this connection, I am able to send custom card attachments and display unique components. I am interested in constructing a component that runs spe ...

Formula for determining the slider's span

I recently created a range slider using Vue.js It has a minimum and maximum value, assumed to be percentages as it ranges from 0 to 100. My goal is to set the minimum value at $5,000 and the maximum at $200,000, However, I struggle with math and need th ...

Tips for configuring Webstorm to automatically change double quotes to single quotes when reformatting source code

After using cmd + alt + l in Webstorm to format my JavaScript code, I noticed that double quotes are used instead of single quotes. How can I configure Webstorm to automatically change the double quotes to single quotes in my code? ...

Disable the option to unsort a column in an antd table (enforce sorting)

To activate sorting on a column, simply use the sortDirections parameter with values ['ascend', 'descend']. With these settings, there are three sorting possibilities: 'ascend', 'descend', and 'unsorted'. ...

Using NPM packages with vanilla JavaScript can be achieved without the need for an HTML file

Is there a way to include an NPM package in my index.js file without installing it via a package manager? I do not have an HTML file, only the index.js file which is executed with 'node index.js' command. Since I cannot use a CDN, is there any me ...

Error TS2694 is being caused by Electron Typescript Material-UI withStyles because the namespace "".../node_modules/csstype/index"" does not have an exported member called 'FontFace'

While I am experienced with Material-UI, I am relatively new to Electron and using React, TypeScript, and Material-UI together. Recently, I encountered an error while attempting to create an electron boilerplate code for future project initialization. Init ...

Not every time you call the AngularJS run method does it actually execute

Working on a simple Angular app, I wanted to implement a user login check and redirection. However, I encountered an issue where accessing the home page from the form site resulted in inconsistent behavior - sometimes redirecting and other times showing ...

Tips for accessing properties from a parent component while utilizing getStaticProps

Issue) Is there a way to pass props from a parent component to a child component when the child component is already receiving data as props from getStaticProps? For instance, consider the Todos component which is a child of a parent component and require ...

Start numerous nodejs servers with just a single command

I currently have multiple Nodejs servers, each stored in its own separate folder within a root directory. Whenever I need to run these servers, I find it cumbersome to navigate through each folder and manually type nodemon *name*. The number of servers i ...