【问题标题】:MobX not updating component properlyMobX 没有正确更新组件
【发布时间】:2020-06-26 15:26:16
【问题描述】:

我对 React/MobX 有点陌生。我正在尝试从仪表板组件中的表单创建一个新项目。创建新项目后, ssoCatalogRegistry 映射和可见项目数组在 MobX 存储中更新,但是页面没有更新任何信息,它在子组件中创建了一个新元素,但没有数据出现。我可以从商店 console.log 来查看数据是否被正确添加。刷新页面后一切正常。在不刷新页面的情况下,是否需要执行其他操作才能获得此结果?

仪表板组件

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);

卡片组件

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 商店 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[] = [];

更新商店中的操作。

//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)

    }
}

==编辑==

它不仅显示“空”链接,而且在 submitSSOLink 操作结束时将其设置回 null 后,Form 组件现在是页面上的绑定元素。

【问题讨论】:

  • 嗯,不知道这里有什么问题,一切看起来都很好,所有组件都包装在观察者中,属性是可观察的。您可以改进的一件事是将visibleItems 更改为computed 属性mobx.js.org/refguide/computed-decorator.html,因此您无需手动分配值
  • 我将 visibleItems 移至 getVisibleItems 计算属性,但看起来它在做同样的事情。只返回“0”。
  • 为什么它甚至呈现“0”?它不应该至少渲染一个Card 组件吗?
  • 所以 0 是我将枚举 LinkType 设置为的值....但是我不知道为什么它会在渲染到页面之前重置 SSOModel 接口...
  • 在您的SSOCatalogCard 中尽量不要解构visibleItems,看看是否有帮助。

标签: reactjs mobx


【解决方案1】:

我最终改变了这个集合

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

到另一组可观察对象,然后将它们应用于提交函数。现在是这样的

//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)
    }
}

可能不是最优雅的解决方案,但它适用于我的场景。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-07
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-11
    • 1970-01-01
    相关资源
    最近更新 更多