简体   繁体   中英

How to re-render one component from another in React

In my React code, I have an Employees page rendering both a Table component and a Filter component. The Filter code manipulates some data stored in the Employees page and then updates the Filter's state through useEffect. The data in question is passed as a prop to both the Filter component and the Table component. However, only the Filter component is re-rendering when this change happens. Excerpts of code below. Sample of filter function:

function filterFunction() {
    let spliceArray = [];
        if ($('#firstNameFilter').val() !== '') {
            for (let i = 0; i < props.employees.length; i++) {
                if(props.employees[i].firstName !== $('#firstNameFilter').val()) {
                    spliceArray.push(i);
                }
            }
            for (let i = spliceArray.length - 1; i >= 0; i--) {
                props.employees.splice(spliceArray[i], 1);
            }
        }
    setUseFilter(true);
}

Sample of employees array on main page:

let employees = [
{
    _id: 2,
    firstName: 'Some',
    lastName: 'One',
    department: 'Somewhere',
    jobTitle: 'Something',
    email: 'ghi@jkl.com',
    phoneExtension: 67890
},
]

Sample of Table rendering code:

<tbody>
                {props.employees.map((employee) => {
                   <tr>
                        <td><i id={employee._id + "upd"} className="fas fa-edit" onClick={handleEdit}></i></td>
                        <td><i id={employee._id + "del"} className="fas fa-trash-alt" onClick={deleteEmployee}></i></td>
                        <td>{employee.firstName}</td>
                        <td>{employee.lastName}</td>
                        <td>{employee.department}</td>
                        <td>{employee.jobTitle}</td>
                        <td>{employee.email}</td>
                        <td>{employee.phoneExtension}</td>
                    </tr>
</tbody>

So ideally, the filter would update the employees array and then the table would re-render with the updated array to reflect only the appropriate parts of the array per the filter. However, currently the array is being updated but the table is not re-rendering.

I am relatively new to React but my understanding was that a component would re-render whenever its state or props changed. Although I am unaware of a way to change the state of the Table component from within the Filter component, it seems like the change in the employees array prop should trigger it.

Any help is appreciated.

Per request, full Employee file below:

import React from 'react';
import Title from '../components/Title/Title.js';
import Table from '../components/Table/Table.js';
import Filter from '../components/Filter/Filter.js';
import { Container, Row, Col } from '../components/Grid/Grid.js';
import axios from 'axios';

let employees = [
{
    _id: 2,
    firstName: 'Some',
    lastName: 'One',
    department: 'Somewhere',
    jobTitle: 'Something',
    email: 'ghi@jkl.com',
    phoneExtension: 67890
},
{
    _id: 3,
    firstName: 'Test',
    lastName: 'McTester',
    department: 'Sales',
    jobTitle: 'Seller',
    email: 'mno@pqr.com',
    phoneExtension: 13579
}];

let employeesControl = [
{
    _id: 2,
    firstName: 'Some',
    lastName: 'One',
    department: 'Somewhere',
    jobTitle: 'Something',
    email: 'ghi@jkl.com',
    phoneExtension: 67890
},
{
    _id: 3,
    firstName: 'Test',
    lastName: 'McTester',
    department: 'Sales',
    jobTitle: 'Seller',
    email: 'mno@pqr.com',
    phoneExtension: 13579
}];

function Employees() {    
    return(
        <Container fluid>
            <Row>
                <Col size="md-12">
                    <Title>Employee Directory</Title>
                </Col>
            </Row>

            <Row>
                <Col size="md-12">
                    <Filter employees={employees} employeesControl={employeesControl}/>
                </Col>
            </Row>

            <Row>
                <Col size="md-12">
                    <Table employees={employees} />
                </Col>
            </Row>
        </Container>
    );
}

export default Employees;

If I understand well, you have and as children of your component.

There is two solutions for your problem:

  1. Manipulate your data in your parent before to pass it down to your child.
  2. Implement a context API (recommanded) to handle a "global context" though your app. This way you will be able to manipulate your data in your component and dispatch the result to update your store (Consider the store as the content of your context). If your component get the state through useContext() hook and pass it as props in your children, then updating the store automatically re-render them. The context Api is pretty easy to understand, you'll just have to learn about the other hooks useReducer() and and useContext() .

For all of this knowledge required, I can only give you the best article I have ever found on this subject: Mixing Hooks and Context API .

The official doc is quite understandable as well and provide clear example of what you need.

Hope this help !

Your main issue is that you are mutating props. In React, you can't mutate props or state. The better way of working with this is to pass a callback function back to the Filter component that calls setState (or the hook equivalent) in the Employees component.

In addition to that, you'll need to make your employees and employeesControl part of the state in Employees component.

The reason for this is because React uses references to determine if values changed and the components need to re-render. It also uses the setState functionalities to tell the components they need to re-render. Then they'll re-render the children as well.

If you need data passed into components that are further away than parent-child and improved data flow, then you can use Context, Redux, or one of the myriad other state management functionalities in the React ecosystem.

In react.js when state or props changed, the component re-rendered. You can mutate state, but you shouldn't mutate props. In react.js props are read-only.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM