How can I modify the props of one child component from a separate child component?

138 views Asked by At

I am working on a scheduling application using Reactjs & Flux. In the application, a user will need to be able to select a specific shift and then assign an employee to cover it. Employee assignment will occur by clicking on an employee's name in a separate list.

Component structure is as follows:

  • Schedule App Component
    • Employee List Component
      • Employee List Item Component
    • Calendar Component
      • Month Component
        • Day Component
          • Shift Component

After selecting a shift by clicking on it, (there are 2 - 5 shifts on any given day) I would like to be able to click on an Employee List Item and have the value of its employeeName prop (this.props.employeeName) assigned to the selected Shift's shiftAssignee prop (this.props.shiftAssignee).

The data for both the calendar and the employees are all generated when the application starts, and stored as separate objects in local storage as 'calendar' and 'employees' respectively. Ultimately I would like to have this data updated as as part of the flux data flow so that I can retain it instead of regenerating it every time the app starts, wiping all the previous data, but that's not my most immediate concern.

The basic structure of that data looks pretty much as follows:

Calendar:

{
    "MonthName": "May",
    "Days": [
        {
            "DayDate": 1,
            "DayName": "Friday",
            "Shifts": [
                {
                    "shiftName": "Day Shift",
                    "required": true,
                    "shiftAssignee": "",
                    "shiftLength": 12
                }
                //remaining shifts
            ],
        }
        //remaining days
    ]
}

Employees:

[
    {
        "name": "F. Last",
        "totalHours": 32,
        "availableHours": 32,
        "assignments": [],
        "commitment": 0.8
    }
    //remaining employees
]

I don't know if this is more information than is needed or if I'm overlooking something that would be crucial for consideration. If more information is needed, just let me know.

3

There are 3 answers

0
Jeremy Baker On BEST ANSWER

I don't believe you need to be concerned with the relationship between the two child components.

In a flux application, the data flows in to the topmost component and is passed down to the children. Looking at it from this way, I believe your question can be rephrased as: "How do I get a child component to change the data from the flux store?"

I've written up a very rough example in a codepen: http://codepen.io/jhubert/pen/ZGJEdp

It's a very lightweight conceptual version of a flux store / dispatcher built into one. I don't recommend copying the example; It's the concept we're after.

Essentially, you want to your Employee List Item Component to modify the data and then let the natural cascading data flow work from there.

# not real code. kind of like coffeescript but really not real.
_data = { { { shiftAssignee: '' } } }
ScheduleAppComponent.setState = _data
EmployeeListItem.onClick = setShiftAssigneeOnData()
ScheduleAppComponent.setState = _data

This stuff is mostly covered at a high level in the flux overview under Structure and Data Flow.

Hope that's helpful! Good luck!

0
Nnamdi Jibunoh On

Your issue seems to be your usage(or lack) of state. I think you might have to extract some of the details to state, so that when it is updated anywhere, it cascades to other parts of the view. Something like "shiftAssignee" in your calendar object seems to be a good parameter to watch as state.

0
ottonomy On

I see you tagged this with reactjs-flux, but it doesn't seem you've thought about implementing Flux stores and actions much so far. Flux is a pattern that could help this data flow happen, but if you're interested in Flux, you kind of need to go all the way and implement stores, actions, and event listeners.

With a Flux implementation of this app, both components should listen to a store event about employee data changing, which could fire whenever an employee is assigned to a shift. Then they can fetch the new data and update their display (to show the shift filled and to show the employee busy during that block/update their scheduled hours total). A different event should be triggered by the selection of an empty shift (an action is created and dispatched, active shift is noted if necessary in the calendar store, an event is emitted to notify the components that a certain shift is ready to be filled), the components can update themselves (maybe asking the store which shift is now active).

It's perfectly natural in a Flux app to have this kind of interdependence and interactivity between different React components, as it's pretty much the case that Flux was invented to solve. A non-Flux approach could also work, but you likely would want to wrap both components in a mutual parent that handles the interactions for them, passing down functions to the components that do the work.