0

I have a React component that I'm trying to pass some props but I get an Uncaught Error: App.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object. when I try to return it inside the snapshot.

// cache settings data
fire.settings = {};
fire.settings.ref = fire.database.ref('settings');

// main app build
class App extends Component {
    render() {
      // get values from firebase
      fire.settings.ref.on('value', function(data) {
        return (<Home settings={data.val()} />);
      });
    }
}

So I started messing around with generators and I get the component to render, but I just get an empty object in my settings prop.

// main app build
class App extends Component {
    render() {
      // get values from firebase
      function* generator() {
        fire.settings.ref.on('value', function(data) {
          fire.settings.snapshot = data.val();
        });
        yield fire.settings.snapshot;
      }
      // init generator and return homepage
      let promise = generator();
      return (<Home settings={promise.next()} />);
    }
}

As well as using componentDidMount()

// main app build
class App extends Component {
    componentDidMount() {
        this.fire.settings.ref.on('value', function(snapshot) {
            this.props.settings = snapshot.val();
        }, (error) => console.log(error), this);
    }
    render() {
        return (<Home settings={this.props.settings}/>);
    }
}

SOLVED

Pass the value through the render to the component

// init render
fire.settings.ref.on('value', function(data) {
  ReactDOM.render(
      <App settings={data.val()}/>, document.getElementById('app'));
});
export default App;

1 Answer 1

2

You are trying to return your element inside callback of a listener which is asynchronous. Instead of that you should set listener inside componentDidMount and call setState inside the callback.

// cache settings data
fire.settings = {};
fire.settings.ref = fire.database.ref('settings');

// main app build
class App extends Component {

  constructor(props) {
    super(props);
    this.state = { data: null };
    this.onSettingsChanged = this.onSettingsChanged.bind(this);
  }

  onSettingsChanged(data){
    this.setState({data: data.val()});
  }

  componentDidMount() {
    fire.settings.ref.on('value', this.onSettingsChanged);
  }

  render() {
    return (<Home settings={this.state.data}/>);
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

I get a couple errors - 1. Warning: getInitialState was defined on App, a plain JavaScript class. This is only supported for classes created using React.createClass. Did you mean to define a state property instead? 2. Uncaught TypeError: Cannot read property 'data' of null
getInitialState() is for ES5 (using React.createClass()). For ES6 classes, you just set the state in the constructor. constructor(props) { super(props); this.state = { data: null }; } Furthermore, for ES6+, you can just set state using a property initializer as such, inside the class: state = { data: null }
Oops! I have messed up with ES5 and ES6 syntax. Fixed it and updated the answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.