1

I am still not as fluent in ReactJS, Ant Design, Sagas and Reducers as I thought I am: I am trying to maintain/ debug a single-page app and I am not sure which files I have to adjust and how.

The goal is to add the following <select> in their render() function within component.tsx:

<Select showSearch
        style={{ width: 150 }}
        placeholder="Select entity" 
        // onChange={(e) => { this.handleSelectorChange("Entity", e) }} // to tackle later
        // value={this.props.selectedEntity.toString()}                 // ------ " ------
>
<Option value="0">Option 0</Option>
   {this.props.availableEntities.map((myEntity) =>
    (<Option key={myEntity.Id.toString()}
             value={myEntity.Id.toString()}>{myEntity.Name}</Option>))}
</Select>

In the respective container.tsx, I added:

const mapStateToProps = (state ) => ({
    availableEntities: GeneralSelectors.getAvailableEntities(state),
});

What I get back is the following is only Option 0 instead of all entities (and even on a wrong place), see screenshot

Screenshot of select options

How do I get my selection options dynamically generated using data from an API? Since I do not see backend being called (using the Network tab of my Chrome debugger), I assume something is wrong with the sagas, but that is just an hypothesis.

Background info

For another single-page-app (SPA) of the same project which already has that <select> inside, I found a urls.ts which looks as follows

import UrlMap from "../UrlMap"
import * as Actions from "./actions"
import * as GeneralActions from "../general/actions"

export const urls = [
    new UrlMap("myWorkingSPA",
        () => [
            Actions.load(),
            GeneralActions.loadEntities(),
            Actions.loadDifferencePositions()
        ])
];

I don't know where this file is actually called, and what I have to modify where in order to include it.

In the respective actions.ts of the running SPA I find

export function loadEntities() : Action {
    return {
        type: LOAD_ENTITIES
    }
}

I am not sure whether my SPA is also taking this actions.ts or not.

The sagas.ts is the same for the running SPA and for my component:

function* loadEntities() {
    const url = config.apiBaseUrl + "/api/Entities";

    try {
        const response: Response = yield fetch(url);
        const json: Interfaces.Entity[] = yield response.json();
        yield put(Actions.setEntities(json));
    } catch (e) {
        notification.error({ message: "Error", description: "Error loading Entities" });
    }
}

function* watchLoadEntities() {
    yield takeEvery(Actions.LOAD_ENTITIES, loadEntities);
}

Hope that was not too much information, but I guess it is all related to the problem.

References

2
  • 1
    "I assume something is wrong with the sagas, but that is just an hypothesis." I'd say that this might be a correct hypothesis. This selector GeneralSelectors.getAvailableEntities(state) should create the slice of the store you need to populate your <Select />. If you track it down, you might find the correct actions that should be dispatched to get your info. As for the other <Select /> component, is the call made during the application startup? When a specific component mounts? Finding when the call is actually made might help you. Commented Feb 20, 2020 at 8:58
  • @Clafou: I wrote an answer instead. Feel free to comment. Commented Feb 20, 2020 at 9:21

1 Answer 1

1

Eventually I also found another sagas.ts which was also in effect:

function* parseUrl({ payload }) {
    const pathName = payload.location.pathname;

    const myComponentURI: match<{}> = matchPath(pathName, { path: config.uiBaseUrl + "myComponent" });
    if (myComponentURI) {
        yield put(GeneralActions.loadEntities()); // <---
    }

   // ... here are many more const. for various different pages
}

The GeneralActions refers to an actions.ts in a directory general.

I solved the issue by putting the marked line. Warning: I believe, this is not the way things should be implemented, I am just saying that it hot-fixed my issue.

As clafou pointed out in a comment, the clean way would be to trigger the yield on startup.

Sign up to request clarification or add additional context in comments.

1 Comment

I don't really know the way your application works so it might totally be correct to do it that way. Using a saga to dispatch some actions in response to another action seems completely normal to me (disclaimer : I'm not a redux-saga expert). Glad you could find a solution to your issue! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.