在reactjs中控制导航栏中的redux属性

时间:2018-03-13 14:56:56

标签: javascript reactjs redux react-redux

我有一个组件(DatasetPage),它为所选图像渲染不同数据集的一些图像。这取决于在导航顶部栏上单击的选项卡。问题是我的情况中的一个数据集非常大,因此加载页面需要更多时间。如果我等到页面加载一切正常但是,如果我在reducer将属性传递给我的组件(ImageWithRelateds)之前单击另一个选项卡(另一个数据集),则新页面将加载另一个(最后一个)的信息数据集,尚未加载。

所以,我已经考虑过一个解决方案,当我有正在运行的加载时,它可以阻止导航栏的导航。但问题是这个加载的东西是在ImageWithRelateds.js组件中控制的,导航栏是从App.js控制的。所以我需要从App.js访问ImageWithRelateds.js的isLoading属性(我已经拥有),但我不知道该怎么做。我刚刚找到了从子级访问父属性但不向后访问的方法。如果你可以帮助我,或者只是提出另一个解决方案,我将非常感激。

App.js

import React, { Component } from 'react';
import { IndexLink } from 'react-router';

import '../styles/app.scss';

class App extends Component {

  constructor(props){
      super(props);
      this.options = this.props.route.data;
  }

  renderContent(){
    if(this.props.route.options) {
      return(<div className="navbar-header nav">
           <a className="navbar-brand" id="title" href="/" >
            IMAGES TEST WEB
          </a>
          <li className="nav-item" key={`key-9999`}>
            <IndexLink to='/home' className="nav-link active" href="#">HOME</IndexLink>
          </li>
          {this.props.route.options.map((opt,i)=>{
            return this.returnOptions(opt,i);
          })}
         </div>
       );
    }
  }


  returnOptions(opt,i){
    return(<li className="nav-item" key={`key-${i}`}>
      <IndexLink to={opt.link} className="nav-link active"
        href="#">{opt.name}</IndexLink>
    </li>);
  }

  render() {
    return (
      <div className="main-app-page">
        <nav className="navbar navbar-default color-navbar fixed">
          <div className="container-fluid">
            {this.renderContent()}
          </div>
        </nav>
        <div className="content">
          {this.props.children}
        </div>
      </div>
    );
  }
}

export default App;

Routes.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Route, IndexRoute, browserHistory, Link } from 'react-router';

import App from './common/App';
import NotFound from './common/NotFound';
import Store from './store';
import Home from './components/Home';

import DatasetPage from './components/Images/DatasetPage';
import ImageWithRelateds from './components/Images/ImageWithRelateds';

import { options_NavBar } from './customize.js';
import { getQimList, resetQimList} from './actions/index';

const Test = ()=>{
  return(<h2 style={{"paddingLeft":"35%"}} >W E L C O M E !</h2>)
};

export default (
    <Route path="/" components={App} options={options_NavBar} history={browserHistory}>
        <IndexRoute components={Test}/>
        <Route path="/home" component={Home} />
        <Route path="images" >
          <Route path="oxford" component={DatasetPage} onEnter={()=>{
                Store.dispatch(resetQimList());
                Store.dispatch(getQimList('oxford'));
             }} />
          <Route path="paris" component={DatasetPage} onEnter={()=>{
                Store.dispatch(resetQimList());
                Store.dispatch(getQimList('paris'));
             }} />
          <Route path="instre" component={DatasetPage} onEnter={(e)=>{

                Store.dispatch(resetQimList());
                Store.dispatch(getQimList('instre'));
             }} />
          <Route path=":id" component={ImageWithRelateds} />
        </Route>

        <Route path="*" component={NotFound} />
    </Route>
);

非常感谢你!

1 个答案:

答案 0 :(得分:1)

父母给孩子们提供道具的反应中最基本的原则之一,孩子们向父亲发出事件(避免双向约束)

所以,你的App.js应该有isLoading变量的状态,而对于ImageWithRelateds组件你应该传递一个这样的事件(函数):

<Route path=":id" render={(props) => <ImageWithRelateds {...props} onFinishLoading={loadingFinished} />}>

和你的组件内部(应该是状态)应该具有这样的功能:

function loadingFinished() {
   this.setState(prev => ({ ...prev, isLoading: false }))
}

然后,如果ImageWithRelateds组件内的加载完成,你会在你内部知道App.js,然后你就可以进行任何你想要的验证

我建议你阅读this article关于将事件(函数)传递给组件,为什么需要它以及如何有效地执行它

希望有所帮助!

修改

你的最终Routes.js代码看起来应该是这样的:

export default class Routes extends React.Component {
  constructor() {
    super();

    this.state = { isLoading: false };

    this.onLoadingFinishded = this.onLoadingFinishded.bind(this);
  }

  onLoadingFinishded() {
    this.setState(state => {
      ...state,
      isLoading: false
    });
  }

  render() {
    return <Route path="/" components={App} options={options_NavBar} history={browserHistory}>
        <IndexRoute components={Test}/>
        <Route path="/home" component={Home} />
        <Route path="images" >
          <Route path="oxford" component={DatasetPage} onEnter={()=>{
                Store.dispatch(resetQimList());
                Store.dispatch(getQimList('oxford'));
             }} />
          <Route path="paris" component={DatasetPage} onEnter={()=>{
                Store.dispatch(resetQimList());
                Store.dispatch(getQimList('paris'));
             }} />
          <Route path="instre" component={DatasetPage} onEnter={(e)=>{

                Store.dispatch(resetQimList());
                Store.dispatch(getQimList('instre'));
             }} />
          <Route path=":id" render={(props) => <ImageWithRelateds 
          {...props} 
          onLoadingFinished={this.onLoadingFinishded} />} />
        </Route>
        <Route path="*" component={NotFound} />
    </Route>
  }
}

(我不能确保代码完全正常运行,因为我没有你的所有项目,但最有可能的是)