反应:当另一个组件发生问题时,如何更新一个组件

时间:2019-02-27 09:58:19

标签: javascript reactjs redux

我有一个带有表的应用程序,该表有一个复选框,可将租户设置为活动状态,此变量是一个全局变量,会影响用户在应用程序其他屏幕上的操作。

在应用程序的右上角,我还有另一个名为ActiveTenant的组件,该组件基本上显示了用户当前正在哪个租户中工作。

enter image description here

表组件的代码如下:

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

我认为这足以说明我的问题。

1 个答案:

答案 0 :(得分:2)

您在此处未正确使用redux。您需要将某个位置保持在您的redux状态中,以表示您的活动租户;这些信息将成为您的唯一事实来源,并将在整个应用程序的各个组件之间共享。每个需要该信息的组件都将连接到该状态的该部分,并且不需要为该信息保留内部状态。

Actions,您可以在其中调用API来获取活动的租户信息或将新的租户设置为活动的。这些操作将调用reducers,这些操作将更改您的redux状态(包括活动的租户信息),而这些redux状态更改将更新您的应用程序组件。

您可能应该花一些时间阅读或重新阅读the redux doc,它简短易懂!