Using Draft Data for Editing Pilots

With those building blocks set, we can now begin updating our <PilotDetails> form to work with the new editing logic and data.

Displaying the Copied Pilot Entry

Since we’re copying edited items from entities to editingEntities, our <PilotDetails> form will need to be able to switch which slice of state it’s reading the pilot data from. We’ll add some additional logic to the mapState function so that it can determine what slice it should use to load the data. We also need to update the action creators to actually dispatch the EDIT_ITEM_EXISTING and EDIT_ITEM_STOP actions at the same time as we dispatch the PILOT_EDIT_START and PILOT_EDIT_STOP actions.

Commit db9b7f7: Add ability to display pilot entry from “draft” editingEntities slice

features/editing/editingSelectors.js

import {createSelector} from "reselect";

import orm from "app/orm";

export const selectEditingEntities = state => state.editingEntities;

export const getEditingEntitiesSession = createSelector(
    selectEditingEntities,
    editingEntities => orm.session(editingEntities)
);

As with our entities slice, we’ll create a memoized selector that ensures we only have a single Redux-ORM Session instance per update to the editingEntities slice.

features/pilots/pilotsActions.js

+import {
+   editExistingItem,
+   stopEditingItem
+} from "features/editing/editingActions";


-export function startEditingPilot() {
-   return {
-       type : PILOT_EDIT_START,
-   };
-}
+export function startEditingPilot(pilotID) {
+   return (dispatch, getState) => {
+       dispatch(editExistingItem("Pilot", pilotID));
+       dispatch({type : PILOT_EDIT_START});
+   }
+}

-export function stopEditingPilot() {
-   return {
-       type : PILOT_EDIT_STOP,
-   };
-}
+export function stopEditingPilot(pilotID) {
+   return (dispatch, getState) => {
+       dispatch({type : PILOT_EDIT_STOP});
+       dispatch(stopEditingItem("Pilot", pilotID));
+   }
+}

We need to dispatch two different actions each time the “Start Editing” and “Stop Editing” buttons are clicked. We’ll change the existing plain action creators into thunks, pass in the pilot IDs as arguments, and dispatch both the pilot-related action and the editing-related action in each thunk.

features/pilots/PilotDetails.jsx

import {getEntitiesSession} from "features/entities/entitySelectors";
+import {getEditingEntitiesSession} from "features/editing/editingSelectors";

// Skip to mapState

    const currentPilot = selectCurrentPilot(state);

+   const pilotIsSelected = Boolean(currentPilot);
+   const isEditingPilot = selectIsEditingPilot(state);
+
+   if(pilotIsSelected) {
+       const session = isEditingPilot ?
+           getEditingEntitiesSession(state) :
+           getEntitiesSession(state);

        const {Pilot} = session;

        if(Pilot.hasId(currentPilot)) {
            pilot = Pilot.withId(currentPilot).ref;
        }
+    }

export class PilotDetails  extends Component {
+   onStartEditingClicked = () => {
+       const {id} = this.props.pilot;
+       this.props.startEditingPilot(id);
+   }

+   onStopEditingClicked = () => {
+       const {id} = this.props.pilot;
+       this.props.stopEditingPilot(id);
=   }

// Omit rendering code
                    <Button
                        primary
                        disabled={!canStartEditing}
                        type="button"
-                       onClick={actions.startEditingPilot}
+                       onClick={this.onStartEditingClicked}
                    >
                        Start Editing
                    </Button>
                    <Button
                        secondary
                        disabled={!canStopEditing}
                        type="button"
-                       onClick={actions.stopEditingPilot}
+                       onClick={this.onStopEditingClicked}
                    >
                        Stop Editing
                    </Button>

We rework the mapState function to determine whether we’re currently editing a pilot or just displaying it. Based on that, we retrieve either the editing Session or the “current data” Session, and read the Pilot out of there.

The <PilotDetails> component gets a couple new click handlers, which extract the pilot ID from props, and call the appropriate action creator.

features/editing/editingReducer.js

    const newItemAttributes = readEntityData(sourceEntities, itemType, itemID);
+   if(newItemAttributes.name) {
+       newItemAttributes.name += " (copied)";
+   }
    const creationPayload = {itemType, itemID, newItemAttributes}

As a visual indicator that we really are displaying the edited item, we’ll temporarily modify our copyEntity() function to append the text " (copied)" to the end of the name field.

If we select a pilot and start editing it, we should now see:

Create a free account to access the full course.

By signing up, you agree to Educative's Terms of Service and Privacy Policy