0

I am kinda new to React/MobX. I am trying to create a new item from a form within my dashboard component. After creating the new item , the ssoCatalogRegistry Map and visible items array get updated in the MobX store, however the page doesn't update with any of the information, it creates a new element in the child component but no data comes along. I can console.log from the store to see that the data is getting added properly. After refreshing the page everything loads fine. Is there something else that needs to be done to get this without a page refresh?

Dashboard component

const SSOCatalogDashboard:React.FC = () => {
    const rootStore = useContext(RootStoreContext);
    const {
        openModal,
        visibleItems,
        loadingStatus,
        loadSSOCatalog} = rootStore.ssoCatalogStore;
    
    useEffect(() => {
        loadSSOCatalog();
        }, [loadSSOCatalog]);

        if(loadingStatus) return <LoadingComponent content='Loading sso links from database' />

    return ( 
        <Container style={{paddingTop: "50px"}}>
            <Row>
                <Col sm={10}>
                    <SSOCatalogForm />
                    <SSOCatalogCard />
                </Col>
               <Col>
                <Button variant="secondary" onClick={openModal}>New Service</Button>
               </Col>
            </Row>
        </Container>
    )
}



export default observer(SSOCatalogDashboard);

Card Component

const SSOCatalogCard:React.FC = () => {
    const rootStore = useContext(RootStoreContext);
    const {
        visibleItems
    } = rootStore.ssoCatalogStore;
    return (
        <Container>
            {visibleItems.map((ssolink: ISSOModel) => (
                <Card style={{ width: '18rem' }}>
                    <Card.Body>
                        <Card.Title>{ssolink.name}</Card.Title>
                        <Card.Subtitle className="mb-2 text-muted">{ssolink.linkType}</Card.Subtitle>
                        <Card.Text>
                            {ssolink.linkDescription}
                        </Card.Text>
                        <Card.Link href={ssolink.url}>{ssolink.url}</Card.Link>
                </Card.Body>
              </Card>
            ))}
        </Container>
    )
}

export default observer(SSOCatalogCard);

MOBX store Observables

rootStore: RootStore;
constructor(rootStore: RootStore) {
    this.rootStore = rootStore;
}
@observable ssoCatalogRegistry = new Map()
@observable loadingStatus:boolean = false;
@observable modalOpen:boolean = false;
@observable SSOLink: ISSOModel = {
    id:"",
    name:"",
    url:"",
    linkType:0,
    owner:"",
    ownerEmail:"",
    linkDescription:""
}
@observable visibleItems: ISSOModel[] = [];

Update action in Store.

//Create new SSO submit. 
@action submitSSOLink = async (e:any) => {
    if (this.SSOLink.id == "") {
        this.SSOLink.id = uuid();
    }
    e.preventDefault();
    this.loadingStatus = true;
    try {
        await agent.Links.create(this.SSOLink);
        runInAction("Creating new SSO Object",() => {
            this.ssoCatalogRegistry.set(this.SSOLink.id,this.SSOLink);
            this.visibleItems = Array.from(this.ssoCatalogRegistry.values());
            console.log(toJS(this.visibleItems));
            this.loadingStatus = false;
            this.modalOpen = false;
            this.SSOLink.id = "";
            this.SSOLink.name = "";
            this.SSOLink.url = "";
            this.SSOLink.linkType = 0;
            this.SSOLink.owner = "";
            this.SSOLink.ownerEmail = "";
            this.SSOLink.linkDescription = "";
        })
    } catch (error) {
        runInAction('create SSO error', () => {
            this.loadingStatus = false;
          });
        console.log(error.response)

    }
}

enter image description here

==Edit==

Not only does it show the "empty" link, after its been set back to null at the end of the submitSSOLink action, the Form component is now bound element on the page.

enter image description here

Parakoopa
  • 505
  • 1
  • 9
  • 22
  • Hmm, not sure what is the problem here, everything looks fine, you have all components wrapped in observer and properties are observables. One thing that you could improve is change `visibleItems` to `computed` property https://mobx.js.org/refguide/computed-decorator.html so you don't need to manually assign value – Danila Jun 26 '20 at 15:48
  • I moved visibleItems to getVisibleItems computed property, however it looks like its doing the same thing. Coming back with just "0". – Parakoopa Jun 26 '20 at 16:57
  • Why it even renders "0"? Shouldn't it render at least one `Card` component? – Danila Jun 26 '20 at 17:21
  • So 0 is the value I set the enum LinkType to....however I don't know why its resetting the SSOModel interface before it renders to the page... – Parakoopa Jun 26 '20 at 17:47
  • Inside your `SSOCatalogCard` try not to destructure the `visibleItems` and see if that helps. – Ivan V. Jun 26 '20 at 18:14
  • What should I use instead? ForEach? – Parakoopa Jun 26 '20 at 18:16
  • I mean you should try: `rootStore.ssoCatalogStore.visibleItems.map()` – Ivan V. Jun 26 '20 at 18:19
  • Ah ok TY. It looks like that is having the same issue. From what I can tell: the bit of code that "resets" this.SSOLink back to its default values is getting ran -> somehow that gets sent to the page.If I change resetting linkType to 3 inside of ssoSubmit, I get 3 on the page instead of 0. – Parakoopa Jun 26 '20 at 18:22

1 Answers1

0

I ended up changing this set

    this.SSOLink.id = "";
    this.SSOLink.name = "";
    this.SSOLink.url = "";
    this.SSOLink.linkType = 0;
    this.SSOLink.owner = "";
    this.SSOLink.ownerEmail = "";
    this.SSOLink.linkDescription = "";

to another set of observables, then applying them on the submit function. It looks like this now

//Create new SSO submit. 
@action submitSSOLink = async (e:any) => {
    this.SSOLink.id = uuid();
    this.SSOLink.name = this.name;
    this.SSOLink.url = this.url;
    this.SSOLink.linkType = this.linkType;
    this.SSOLink.owner = this.owner;
    this.SSOLink.ownerEmail = this.ownerEmail;
    this.SSOLink.linkDescription = this.linkDescription;
    e.preventDefault();
    this.loadingStatus = true;
    try {
        await agent.Links.create(this.SSOLink);
        runInAction("Creating new SSO Object",() => {
            this.ssoCatalogRegistry.set(this.SSOLink.id,this.SSOLink);
            this.visibleItems = Array.from(this.ssoCatalogRegistry.values());
            this.loadingStatus = false;
            this.modalOpen = false;
            this.name = "";
            this.url = "";
            this.linkType = 0;
            this.owner = "";
            this.ownerEmail = "";
            this.linkDescription = "";
        })
    } catch (error) {
        runInAction('create SSO error', () => {
            this.loadingStatus = false;
          });
        console.log(error.response)
    }
}

Probably not the most elegant solution, but it worked with my scenario.

Parakoopa
  • 505
  • 1
  • 9
  • 22