简体   繁体   中英

Trying to pass a parent state to child component in react

I am trying to pass the username of the user's spotify account via the spotify webAPI from my parent component (in app.js) to a child component in ./components/header.js.

When passing my state variable into the component as a prop, I get an error for

TypeError: Cannot read property 'name' of undefined

I will post the code for my main component as well as my header component and the index.js file. In my main app.js file you will see commented code near the bottom. This code works as intended. It is basically the same code from my Header component, but without it being in a component. In this code, using {this.state.serverData.user.name} works as expected and outputs the user's username on the webpage. The other way gives the above error. Suggestions? I am new to react.

App.js:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import queryString from 'query-string';
import Header from './Components/header';
import ButtonTest from './Components/buttonTest';


let textColor = 'orange'
let defaultStyle = {
  color: textColor
};


class App extends Component {

    constructor() {
        super();
        this.state = { serverData: {} }
    }
    componentDidMount() {
        let parsed = queryString.parse(window.location.search);
        let accessToken = parsed.access_token;

        fetch('https://api.spotify.com/v1/me', {
            headers: { 'Authorization': 'Bearer ' + accessToken }
        }).then((response) => response.json()).then(data => this.setState({ 
serverData: { user: { name: data.display_name } } }))



    }
    render() {

     const headerStyle = { color: 'orange', 'font-size': '50px' }
     return (
            <div className="App">


             <Header userName={this.state.serverData.user.name}/> 
             <ButtonTest/>

            </div>

         /*<div className="App"> 
                {
                    this.state.serverData.user ?
                        <div>
                            <h1 style={headerStyle}>
                                Welcome, 

                                    {this.state.serverData.user.name}
                            </h1>


                            <div>

                                <button onClick={() => window.location = 
'http://localhost:8080/clef.html'}
                                >Click here to search for song 
information</button>
                            </div>
                        </div> : <button onClick={() => window.location = 
'http://localhost:8888/login'}
                            style={defaultStyle}>Log in with Spotify</button>

             }
             <ButtonTest />

            </div>*/


        );
}
}




export default App;

header.js

import React, { Component } from 'react';


let textColor = 'orange'
let defaultStyle = {
    color: textColor
};

export default class Header extends Component {
    constructor(props) {
        super(props);

    }
    render() {
        const headerStyle = { color: 'orange', 'font-size': '50px' }
        return (
            <div className="App">
                {
                    this.props.userName ? 
                        <div>
                            <h1 style={headerStyle}>
                                Welcome,
              {
                                    this.props.userName}
                            </h1>


                            <div>

                                <button onClick={() => window.location = 
'http://localhost:8080/clef.html'}
                                >Click here to search for song 
information</button>
                            </div>
                        </div> : <button onClick={() => window.location = 
'http://localhost:8888/login'}
                            style={defaultStyle}>Log in with Spotify</button>
                }
            </div>
        );
    }
  }

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import Header from './Components/header';

ReactDOM.render(<App />, document.getElementById('root'), );

I suspect your problem is with this line:

<Header userName={this.state.serverData.user.name}/>

Basically, when you initialise your app component, you have a state.serverData = {} , so on first render it is going to try and access user.name , and because no user has loaded yet, you get your error.

You can fix this by either initialising your state to include an empty user object. Eg.

this.state = { serverData: { user: {} } }

or you can add an && check when passing the prop.

const sData = this.state.serverData
<Header userName={sData.user && sData.user.name}/>`

Or if you are able to use the newer ?. syntax (optional chaining), you could do

<Header userName={this.state.serverData.user?.name}/> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM