【问题标题】:callback render loses router context for child react-router & redux回调渲染丢失子 react-router 和 redux 的路由器上下文
【发布时间】:2017-06-26 14:27:10
【问题描述】:

我一直在构思一个想法,但遇到了一些不寻常的事情(我的大脑在 react-router 上受伤)。

我正在尝试使用 .map 从返回的对象(多个相似对象)动态呈现项目列表,并将它们附加到render(){return(<div />)}

我只是不知道调用一个函数然后.map这个回调的结果。

我认为我这样做的方式意味着渲染的项目失去了上下文。 react-router <Link /> 将在正常流程中按预期运行(放置在 render(){return(<div />)} 内),但在从渲染外部创建项目时不会。我已经在代码下方发布了错误。

我已经阅读了许多使用上下文和位置/历史以及 withRouter 解决此问题的不同方法。坦率地说,我迷路了。

如果有人可以查看我下面的示例并指导我朝着正确的方向前进,我将不胜感激。

几点说明: - 主要焦点似乎是神秘的 - 我知道我有很多不必要的进口 - 为了清楚起见,我会被剥离,否则我会迷路

索引

import _ from 'lodash';
import React from 'react';
import { render } from 'react-dom';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
import { Provider } from 'react-redux';
import { store, history } from './store';

import Main from './Main';
import { routyr } from './Menu';

// remaining paths in Menu.js (routyr) for menu visibility
const router = (
  <Provider store={store}>
    <Router history={history}>
      <Route path="/" component={Main}>
        {routyr}
      </Route>
    </Router>
  </Provider>
)

render (router, document.getElementById('app'));

主要

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actionCreators from './actionCreators';

import App from './app';

function mapStateToProps(state){
  return{
    info: state.info,
    myProfile: state.myProfile
  }
}

function mapDispatchToProps(dispatch){
  return { actions: bindActionCreators(actionCreators, dispatch) }
}

const Main = connect(mapStateToProps, mapDispatchToProps)(App);
export default Main;

路由器

import React from 'react';
import { Link } from 'react-router';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
import { Provider } from 'react-redux';

import { store, history } from './store';

//pages
import App from './app';
import Landing from './Landing';
import Me from './mystuff';
import ViewStuff from './viewStuff';

//Routes for index.js
export const routyr = (
  <span>
    <IndexRoute component={Landing} />
    <Route path="/myStuff" component={Me} />
    <Route path="/viewStuff" component={ViewStuff} />
  </span>
)

//Menu types
//loaded by app.js
export const menuLoggedIn = (
  <div className="MainMenu">
    <Link to='/' className="buttonA green">Home</Link>
    <Link to='myStuff' className="buttonA green">My Stuff</Link>
  </div>
);
export const menuLoggedOut = (
  <div className="MainMenu">
    <Link to='/login' className="buttonA green">Login</Link>
  </div>
);

应用程序

import React from 'react';
import _ from 'lodash';
import { Link } from 'react-router';
import auth from './auth';
import Landing from './Landing';
import Header from './Header';
import { menuLoggedIn, menuLoggedOut } from './Menu';

export default class App extends React.Component {
  constructor(){
    super();
    this.state={
      auth: auth.loggedIn(),
      menu: null
    };
  }

  componentWillMount(){
    if (this.state.auth==true) {
      this.setState({
        menu: menuLoggedIn
      })
    }else{
      this.setState({
        menu: menuLoggedOut
      });
    }
  }

  render(){
    return (
      <div>
        <Header />
        {this.state.menu}<br />
        <div id="view">
          {React.cloneElement(this.props.children, this.props)}
        </div>
      </div>
    );
  }
};

神秘的

import React, { PropTypes } from 'react';
import { render } from 'react-dom';
import { Link } from 'react-router';
import { withRouter } from 'react-router';
import { Provider } from 'react-redux';

import * from './whacks';

export default class Me extends React.Component{
  constructor(){
    super();
  }
  componentDidMount() {

    function listThem(oio){
      oio.map(function(ducks){
        render(

          <div className="ListItem">
            <Link to="/viewStuff"> _BROKEN_ View Stuff</Link>
            <div className="listLabel">{ducks.type}</div>
            <h3>{ducks.description.title}</h3>
            {ducks.description.long}
          </div>, document.getElementById('fishes').appendChild(document.createElement('div'))

        );
      });
    }

    var some = new Whacks();

    some.thing(more, (close, open) => {

      if(close){
        console.log(close));
      } else {
        doIt(open);
      }

    });
  }

  render(){
    return(
      <div>
        <Link to="viewStuff"> _WORKING_ View Stuff</Link>
        <div id="fishes">
        </div>
      </div>
    )
  }
}

商店

import { createStore, compose } from 'redux';
import { syncHistoryWithStore } from 'react-router-redux';
import { browserHistory } from 'react-router';
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';

/*-------ROOT REDUCER---------*/
/*-------DEFAULT STATES---------*/
/*-------CREATE STORE---------*/
/*-------INTEGRATE HISTORY---------*/

import me from './reducers/obj';
import myProfile from './reducers/myProfile';

const rootReducer = combineReducers(
  {
    routing: routerReducer,
    me,
    myProfile
  }
);

//TEMP remove harcoded var
const uuidSet = "fa78d964";
export const defaultState = {
  uuid: uuidSet,
};

export const store = createStore(rootReducer, defaultState, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
export const history = syncHistoryWithStore(browserHistory, store);

动作创作者

export function me (obj){
  return {
    type: "ADD_OBJECTLIST",
    obj
  }
}

export function myProfile (dump){
  return {
    type: "MY_DATA",
    dump
  }
}

来自 package.json

"react-redux": "^5.0.2",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.7",
"redux": "^3.6.0",

错误

未捕获的错误:在路由器上下文之外渲染的 s 无法导航。

@UG, 我在 mystuff 中尝试了以下方法:

constructor(){
  super();
  this.state={
    oio: {}
  };
}

some.thing(more, (close, open) => {

      if(close){
        console.log(close));
      } else {
        this.setState({
          oio: open
        });
      }

});

render(){
  let flat = this.state.oio;
  flat.map(function(ducks){
    return (
      <div className="ListItem">
        <Link to="/viewStuff">View Stuff</Link>
        <div className="listLabel">{ducks.type}</div>
        <h3>{ducks.description.title}</h3>
        {ducks.description.long}
      </div>
    )
  })
}

并接收

未捕获的类型错误:flat.map 不是函数 在 Me.render

【问题讨论】:

    标签: javascript redux react-router react-router-redux


    【解决方案1】:

    非常感谢 UG_ 用 state 打我的耳朵。 我已经拉入了一个组件并从回调对象创建了每个组件道具。 mystuff中我的工作解决方案如下:

    constructor(props){
      super(props);
      this.state={
        oio: []
      }
    }
    componentDidMount() {
    
      let listThem = (stuff) => {
        let ioi = [];
        stuff.forEach(function(dood, index, array) {
          let lame = <MyItem plop={dood} key={index} />;
          ioi.push(lame);
        });
        return (
          this.setState({
            oio: ioi
          })
        );
      }
    
      var some = new Whacks();
      some.thing(more, (close, open) => {
        if(close){
          console.log(close));
        } else {
          listThem(open);
        }
      });
    
    }
    render(){
      return(
        <div>
          {this.state.oio}
        </div>
      )
    }
    

    它使用来自每个返回对象的道具呈现 MyItem 组件的新副本。所以现在我返回的项目包含上下文!

    【讨论】:

    • 理想!我会在渲染 fn 中做 &lt;MyItem/&gt; 的事情,而不是将其设置为状态。我只是将对象/数组设置为状态
    【解决方案2】:

    我不确定我是否完全解决了您的问题。但我认为你想在myStuffrender() 方法中使用 Link 您可以将其更改为以下内容:

    render(){
    return(
      <div>
        <Link to="viewStuff"> _WORKING_ View Stuff</Link>
        <div id="fishes">
            {
                oio.map(function(ducks){
                    return (
                        <div className="ListItem">
                            <Link to="/viewStuff"> _BROKEN_ View Stuff</Link>
                            <div className="listLabel">{ducks.type}</div>
                            <h3>{ducks.description.title}</h3>
                            {ducks.description.long}
                        </div>
                    );
                }
        </div>
      </div>
        )
    }
    

    根据詹姆斯的评论,

    您应该使用反应状态来维护 oio 对象。

    constructor() {
     super(); 
     //init
     this.setState({oio : {}});
    }
    

    并在异步调用中更新状态,当状态更新时,组件可以重新渲染。

    【讨论】:

    • 我希望是这样。我的问题是 oio 对象是来自 componentDidMount 中 some.thing 的异步回调。
    • 更新了答案
    • 我很困惑我怎么没想到。谢谢!
    • 因为我无法在渲染中映射对象。这些是非常嵌套的对象。
    • 你能给我这个对象的结构吗?如果做得好,我认为我们可以让它发挥作用,我一直都这样做
    猜你喜欢
    • 2020-09-12
    • 2017-04-16
    • 2016-03-26
    • 2017-01-05
    • 2018-01-06
    • 2016-02-22
    • 2017-06-08
    • 2017-03-18
    • 2021-10-16
    相关资源
    最近更新 更多