Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
96 views
in Technique[技术] by (71.8m points)

javascript - Using state from components not loaded with react-router-dom

I re-formatted the question with an example using the star wars API. The problem I am having is trying to use state from PeoplePage and passing to the CounterPage while using react-router-dom. This is a small example of my real website. I am trying to narrow down the actual issue with this example. I hope this clarifies what I am working to achieve. Thanks!

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

question from:https://stackoverflow.com/questions/65623428/using-state-from-components-not-loaded-with-react-router-dom

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I'm not entirely sure what your app code is supposed to be doing, but when I copy/pasted your code snippets into a codesandbox there were a few issues I had to address before the code would run.

Issues

  1. Each Route's render prop wasn't returning a render function.
  2. Each Route's path prop wasn't an absolute path.
  3. PeoplePage's state update was incorrectly updating its state. Doesn't access the correct previous state, i.e. state isn't a number so this.state + 1 won't work.
  4. CounterPage consumes and renders only a count prop, but isn't passed this prop.

Fixes

Routes

<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>
    )
  }
/>

PeoplePage

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

Edit using-state-from-components-not-loaded-with-react-router-dom


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...