0
votes

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

1
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 mobx.js.org/refguide/computed-decorator.html so you don't need to manually assign value - Danila
I moved visibleItems to getVisibleItems computed property, however it looks like its doing the same thing. Coming back with just "0". - Parakoopa
Why it even renders "0"? Shouldn't it render at least one Card component? - Danila
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
Inside your SSOCatalogCard try not to destructure the visibleItems and see if that helps. - Ivan V.

1 Answers

0
votes

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.