【问题标题】:Using state from components not loaded with react-router-dom使用未加载 react-router-dom 的组件的状态
【发布时间】:2021-04-13 19:58:11
【问题描述】:

我用一个使用星球大战 API 的示例重新格式化了这个问题。 我遇到的问题是尝试使用来自 PeoplePage 的状态并在使用 react-router-dom 时传递给 CounterPage。这是我真实网站的一个小例子。我试图用这个例子缩小实际问题的范围。我希望这能澄清我正在努力实现的目标。谢谢!

import React from 'react';
import {BrowserRouter as Router,Switch,Route} from 'react-router-dom';

class ExampleApp extends React.Component{
    constructor(){
        super()
        this.state = {
            starWarsPeople:[],
            stateNumber:0
        }
    }
    numberHandler(number){
        console.log('number',number)
        this.setState({stateNumber: this.state.stateNumber + number})
    }
    componentDidMount(){
        fetch('https://swapi.dev/api/people')
        .then(response => response.json())
        .then(data =>this.setState({starWarsPeople:data}))

    }
    render(){
        const {starWarsPeople,stateNumber} = this.state
        console.log(stateNumber);
        return(
            <Router>
                <div>
                    <Switch>
        /* Issue----->*/ <Route path ='/people' exact render = /*Render is where I am stuck */
                            {starWarsPeople.length !==0
                                ?
                                <PeoplePage prop1 = {starWarsPeople} increment ={this.numberHandler.bind(this)}/>
                                :
                                <div>loading...</div>
                            }
                        />
        /* Issue----->*/ <Route path ='/counter' exact render = 
                        /*render is where I am stuck, interval will not go to count prop when this is loaded*/
                            {starWarsPeople.length !==0
                                ?
                                /*this example will render but not sure if its right and the interval will not work:
                                <Route path ='/counter' exact render = {
                                (props)=><CounterPage {...props} people ={starWarsPeople} key = {stateNumber}/>}/> */
                                <CounterPage people ={starWarsPeople} key = {stateNumber}/*I want this to re-render every time the inverval changes *//>
                                :
                                <div>loading...</div>
                            }
                        />
                    </Switch>
                </div>
            </Router>
        )
    }
}
export default ExampleApp;


class PeoplePage extends React.Component {
    constructor(props){
        super(props)
        this.state ={
            number:0
        }
    }
    componentDidMount(){
        this.myInterval = setInterval(()=>{
            this.setState({state:this.state+1})
            this.props.increment(1);
        },1000)
    }
    componentWillUnmount(){
        clearInterval(this.myInterval);
    }
    render(){
    return(
        <div>
            {this.props.prop1.results[0].name}
        </div>
    )
    }
}

const CounterPage =({count})=>{
    return(
        <div>{count}</div>
    )
}

【问题讨论】:

  • 嗨,欢迎来到 stackoverflow。您能否更新您的问题以包含Minimal, Complete, and Reproducible 代码示例?还请详细说明您的问题。问题是什么,是否有错误等等。我对您的代码尝试对 &lt;prop&gt; = {&lt;this.state&gt;} &lt;prop&gt;={&lt;this.state&gt;} key={&lt;this.state&gt;} 执行的操作感到有些困惑,因为它似乎根本不是有效的 JSX。
  • @DrewReese 为了清楚起见,我更新了问题。感谢您的观看。

标签: javascript reactjs react-router-dom


【解决方案1】:

我不完全确定您的应用代码应该做什么,但是当我将您的代码 sn-ps 复制/粘贴到代码沙箱中时,我必须在代码运行之前解决一些问题。

问题

  1. 每个 Routerender 道具都没有返回渲染函数。
  2. 每个Routepath 属性都不是绝对路径。
  3. PeoplePage 的状态更新错误地更新了它的状态。无法访问正确的先前状态,即状态不是数字,因此 this.state + 1 将不起作用。
  4. CounterPage 只消耗和渲染一个 count 道具,但没有传递这个道具。

修复

路线

<Route
  path="/people" // <-- fix path
  exact
  render={(routeProps) => // <-- use a render function to return UI
    starWarsPeople.length !== 0 ? (
      <PeoplePage
        prop1={starWarsPeople}
        increment={this.numberHandler.bind(this)}
        {...routeProps} // <-- pass on route props
      />
    ) : (
      <div>loading...</div>
    )
  }
/>
<Route
  path="/counter" // <-- fix path
  exact
  render ={(routeProps) => // <-- use a render function to return UI
    starWarsPeople.length !== 0 ? (
      <CounterPage
        people={starWarsPeople}
        count={stateNumber} // <-- pass count prop
        key={stateNumber}
        {...routeProps} // <-- pass on route props
      />
    ) : (
      <div>loading...</div>
    )
  }
/>

人物页面

class PeoplePage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      number: 0
    };
  }
  componentDidMount() {
    this.myInterval = setInterval(() => {
      this.setState(({ number }) => ({ number: number + 1 }));
      this.props.increment(1);
    }, 1000);
  }
  componentWillUnmount() {
    clearInterval(this.myInterval);
  }
  render() {
    return <div>{this.props.prop1.results[0].name}</div>;
  }
}

【讨论】:

  • 路线有效!感谢您花时间提供帮助。我想要做的主要事情是让计时器运行,无论采用什么路线,并让它在 App.js 中更新状态而不被重新渲染。现在我有一个计时器组件隐藏在应用程序的标题后面,它永远不会重新渲染。不确定它是否完全正确,但它可以工作。再次感谢您。
猜你喜欢
  • 2021-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-26
  • 1970-01-01
  • 2023-01-28
  • 1970-01-01
相关资源
最近更新 更多