簡體   English   中英

React:當另一個組件發生某些事情時如何更新一個組件

[英]React: How to update one component, when something happens on another component

我有一個帶有表的應用程序,該表有一個復選框來將租戶設置為活動,這個變量是一個全局變量,它影響用戶在應用程序的其他屏幕中所做的事情。

在應用程序的右上角,我有另一個名為 ActiveTenant 的組件,它基本上顯示了用戶目前在哪個租戶中工作。

在此處輸入圖片說明

table組件的代碼是這樣的:

import React, { Component } from 'react';
import {  Table, Radio} from 'antd';
import { adalApiFetch } from '../../adalConfig';
import Notification from '../../components/notification';

class ListTenants extends Component {

    constructor(props) {
        super(props);
        this.state = {
            data: []
        };
    }



    fetchData = () => {
        adalApiFetch(fetch, "/Tenant", {})
          .then(response => response.json())
          .then(responseJson => {
            if (!this.isCancelled) {
                const results= responseJson.map(row => ({
                    key: row.id,
                    TestSiteCollectionUrl: row.TestSiteCollectionUrl,
                    TenantName: row.TenantName,
                    Email: row.Email
                  }))
              this.setState({ data: results });
            }
          })
          .catch(error => {
            console.error(error);
          });
      };


    componentDidMount(){
        this.fetchData();
    }

    render() {
        const columns = [
                {
                    title: 'TenantName',
                    dataIndex: 'TenantName',
                    key: 'TenantName',
                }, 
                {
                    title: 'TestSiteCollectionUrl',
                    dataIndex: 'TestSiteCollectionUrl',
                    key: 'TestSiteCollectionUrl',
                }, 
                {
                    title: 'Email',
                    dataIndex: 'Email',
                    key: 'Email',
                }
        ];

        // rowSelection object indicates the need for row selection
        const rowSelection = {
            onChange: (selectedRowKeys, selectedRows) => {
                if(selectedRows[0].TenantName != undefined){
                    console.log(selectedRows[0].TenantName);
                    const options = { 
                        method: 'post'
                    };

                    adalApiFetch(fetch, "/Tenant/SetTenantActive?TenantName="+selectedRows[0].TenantName.toString(), options)
                        .then(response =>{
                        if(response.status === 200){
                            Notification(
                                'success',
                                'Tenant set to active',
                                ''
                                );
                        }else{
                            throw "error";
                        }
                        })
                        .catch(error => {
                        Notification(
                            'error',
                            'Tenant not activated',
                            error
                            );
                        console.error(error);
                    });
                }
            },
            getCheckboxProps: record => ({
                type: Radio
            }),
        };

        return (
            <Table rowSelection={rowSelection} columns={columns} dataSource={this.state.data} />
        );
    }
}

export default ListTenants;

而 ActiveTenant 組件的代碼也很簡單

import React, { Component } from 'react';
import authAction from '../../redux/auth/actions';
import { adalApiFetch } from '../../adalConfig';

class ActiveTenant extends Component {
  constructor(props) {
    super(props);
    this.state = {
      tenant: ''
    };
  }

  fetchData = () => {
    adalApiFetch(fetch, "/Tenant/GetActiveTenant", {})
      .then(response => response.json())
      .then(responseJson => {
        if (!this.isCancelled) {
          this.setState({ tenant: responseJson.TenantName });
        }
      })
      .catch(error => {
        this.setState({ tenant: '' });
        console.error(error);
      });
  };


componentDidMount(){
    this.fetchData();
}

  render() {
    return (
      <div>You are using tenant: {this.state.tenant }</div>
    );
  }
}
export default ActiveTenant;

問題是,如果我在我的數據庫上注冊了多個租戶並將它們設置為活動狀態,則會發生服務器端操作,並且狀態會發生變化,但是在右上角它仍然顯示舊租戶為活動狀態,直到我按 F5刷新瀏覽器。

我怎樣才能做到這一點?

為了完全理解我的代碼,我需要在其他組件下面粘貼:

  1. 包含活動租戶的 TopBar

     import React, { Component } from "react"; import { connect } from "react-redux";import { Layout } from "antd"; import appActions from "../../redux/app/actions"; import TopbarUser from "./topbarUser"; import TopbarWrapper from "./topbar.style"; import ActiveTenant from "./activetenant"; import TopbarNotification from './topbarNotification'; const { Header } = Layout; const { toggleCollapsed } = appActions; class Topbar extends Component { render() { const { toggleCollapsed, url, customizedTheme, locale } = this.props; const collapsed = this.props.collapsed && !this.props.openDrawer; const styling = { background: customizedTheme.backgroundColor, position: 'fixed', width: '100%', height: 70 }; return ( <TopbarWrapper> <Header style={styling} className={ collapsed ? "isomorphicTopbar collapsed" : "isomorphicTopbar" } > <div className="isoLeft"> <button className={ collapsed ? "triggerBtn menuCollapsed" : "triggerBtn menuOpen" } style={{ color: customizedTheme.textColor }} onClick={toggleCollapsed} /> </div> <ul className="isoRight"> <li onClick={() => this.setState({ selectedItem: 'notification' })} className="isoNotify" > <TopbarNotification locale={locale} /> </li> <li> <ActiveTenant /> </li> <li onClick={() => this.setState({ selectedItem: "user" })} className="isoUser" > <TopbarUser /> <div>{ process.env.uiversion}</div> </li> </ul> </Header> </TopbarWrapper> ); } } export default connect( state => ({ ...state.App.toJS(), locale: state.LanguageSwitcher.toJS().language.locale, customizedTheme: state.ThemeSwitcher.toJS().topbarTheme }), { toggleCollapsed } )(Topbar);

App.js 包含頂部欄

import React, { Component } from "react";
import { connect } from "react-redux";
import { Layout, LocaleProvider } from "antd";
import { IntlProvider } from "react-intl";
import { Debounce } from "react-throttle";
import WindowResizeListener from "react-window-size-listener";
import { ThemeProvider } from "styled-components";
import authAction from "../../redux/auth/actions";
import appActions from "../../redux/app/actions";
import Sidebar from "../Sidebar/Sidebar";
import Topbar from "../Topbar/Topbar";
import AppRouter from "./AppRouter";
import { siteConfig } from "../../settings";
import themes from "../../settings/themes";
import { themeConfig } from "../../settings";
import AppHolder from "./commonStyle";
import "./global.css";
import { AppLocale } from "../../dashApp";
import ThemeSwitcher from "../../containers/ThemeSwitcher";



const { Content, Footer } = Layout;
const { logout } = authAction;
const { toggleAll } = appActions;
export class App extends Component {
  render() {
    const { url } = this.props.match;
    const { locale, selectedTheme, height } = this.props;
    const currentAppLocale = AppLocale[locale];
    return (
      <LocaleProvider locale={currentAppLocale.antd}>
      <IntlProvider
        locale={currentAppLocale.locale}
        messages={currentAppLocale.messages}
      >
      <ThemeProvider theme={themes[themeConfig.theme]}>
        <AppHolder>
          <Layout style={{ height: "100vh" }}>
            <Debounce time="1000" handler="onResize">
              <WindowResizeListener
                onResize={windowSize =>
                  this.props.toggleAll(
                    windowSize.windowWidth,
                    windowSize.windowHeight
                  )
                }
              />
            </Debounce>
            <Topbar url={url} />
            <Layout style={{ flexDirection: "row", overflowX: "hidden" }}>
              <Sidebar url={url} />
              <Layout
                className="isoContentMainLayout"
                style={{
                  height: height
                }}
              >
                <Content
                  className="isomorphicContent"
                  style={{
                    padding: "70px 0 0",
                    flexShrink: "0",
                    background: "#f1f3f6",
                    position: "relative"
                  }}
                >
                  <AppRouter url={url} />
                </Content>
                <Footer
                  style={{
                    background: "#ffffff",
                    textAlign: "center",
                    borderTop: "1px solid #ededed"
                  }}
                >
                  {siteConfig.footerText}
                </Footer>
              </Layout>
            </Layout>
            <ThemeSwitcher />
          </Layout>
        </AppHolder>
      </ThemeProvider>
      </IntlProvider>
      </LocaleProvider>
    );
  }
}

export default connect(
  state => ({
    auth: state.Auth,
    locale: state.LanguageSwitcher.toJS().language.locale,
    selectedTheme: state.ThemeSwitcher.toJS().changeThemes.themeName,
    height: state.App.toJS().height
  }),
  { logout, toggleAll }
)(App);

我認為這應該足以說明我的問題。

您在那里沒有正確使用 redux。 您需要將您的活動租戶保留在您的 redux 狀態中; 該信息將成為您的唯一真實來源,並將在整個應用程序的組件之間共享。 每個需要該信息的組件都將連接到狀態的那​​部分,並且不需要為該信息保存內部狀態。

Actions ,您可以在其中調用 API 以獲取活動租戶信息或將新租戶設置為活動租戶。 這些操作將調用reducer來更改您的 redux 狀態(包括您的活動租戶信息),並且這些 redux 狀態更改將更新您的應用程序組件。

您可能應該花一些時間閱讀或重新閱讀redux 文檔,它簡短且解釋得很好!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM