1

I have one question about the react-way.

I have two components. For example: App & Browser.

  • App is a general component. It loads inner modules and renders application tree-structure
  • Browser is an inner-component of App. It shows some fetched data by its ID.

App-component doesn't matter about ID and data what currently rendered in Browser-component. App doesn't want to control browser-component's navigation. Browser is mostly independent.

But sometimes App wanna do one of it:

  • Ask Browser-component for refresh (fetch data again + render it) active page
  • Ask Browser-component to load particular ID

I don't understand how I can do it using react-way with props.

Some code for example:

class App extends Component {
  render(){
    return ... <Browser server={this.server}/> ...;
  }
}

class Browser extends Component {
  constructor(props){
     super(props);
     this.state = { id: 'default' };
  }

  componentDidMound() { this.checkData(); }
  componentWillUpdate() { this.checkData(); }

  async checkData(){
      if(!this.state.data}{
          const data = await this.props.server.fetch(this.state.id);
          this.setState({ data });
      }
  }

  onChange(newId){
     this.setState({ data: null, id: newId });
  }

  render(){
    return <div>
        <Page data={this.state.data}/>
        <Navigation activeId={this.state.id} onChange={::this.onChange}/>
    </div>;
  }
}

I have some bad idea's. Example:

  • I can set Browser to App by ref-attribute. And directly run needed methods
  • I can use global variables
  • I can provide empty {}-object into Browser-component. In initialization in browser-component set all needed methods into this object. Finally run it from App

I think all this variants isn't react-way. How I can do it right? I don't use redux in this project. Just react.

faiwer
  • 1,808
  • 1
  • 15
  • 17
  • When do you want your `App` to trigger `Browser` for refresh? I mean the event of trigger? – Jyothi Babu Araja Dec 09 '16 at 13:45
  • When user is using NFC-tag or bluetooth tag. – faiwer Dec 09 '16 at 13:50
  • whenever you do `setState()` inside `App` component it will run render method, so the `Browser`'s `componentWillUpdate` will be called, so this way it should call your `checkData` method – iurii Dec 09 '16 at 13:51
  • so basically you will need some state inside `App` in order to trigger UI updates – iurii Dec 09 '16 at 13:56
  • componentWillUpdate will be called. I can put there checkData(). But it won't do anything, because it looks at state.id instead props.id. State.id didn't change. App can't change child state. App can change only child props. But child is independent, therefore it can use either state.id or props.id, but not together. – faiwer Dec 09 '16 at 13:56
  • so you want to send `id` to your `Browser` component? – Jyothi Babu Araja Dec 09 '16 at 13:59
  • Ok. Let them App has state { id: string }. It can provide it into Browser-component. But browser either use it instead self state.id, or use self state.id instead props.id. In first variant I need to make all logic in App. In second I can't trigger some methods in Browser. I'm in a trap :( – faiwer Dec 09 '16 at 13:59
  • where do you get `id`? is it coming from fetch result? – iurii Dec 09 '16 at 14:01
  • Browser component is a navigation wrapper for Page component. It contains of all navigation logic code and renders only one Page component. It's a "container component". Page is presentation component. App is main application wrapper component. Browser initially loads default ids. And changes it when user click's in Page component. – faiwer Dec 09 '16 at 14:07
  • It turns out that Browser component has 2 sources of ID. It's a main problem? It's a wrong situation? – faiwer Dec 09 '16 at 14:08
  • What about ``, then `this.refs['browser'].onChange( id )` from App? https://jsfiddle.net/69z2wepo/64772/ – pawel Dec 09 '16 at 14:09
  • pawel, yes! It's my 1st "dirty" decision from this topic :) Do you think that is an acceptable decision? I'm newbie in React and don't know how to do it right. – faiwer Dec 09 '16 at 14:12
  • I think "ref"-mechanism is intended for custom DOM logic on browser real-DOM components. Hard animations, perfomance, etc. Also for DOM logic on non-react component. – faiwer Dec 09 '16 at 14:16
  • 1
    @faiwer I guess this is the very case for `refs` being introduced in React – pawel Dec 09 '16 at 14:16
  • Possible duplicate of [React refs with components](http://stackoverflow.com/questions/25941585/react-refs-with-components) – Jed Fox Dec 09 '16 at 15:37
  • Simple example: http://codepen.io/anon/pen/pNZLXr – faiwer Dec 10 '16 at 11:45

1 Answers1

0

I found one interesting decision. I can pass observer-method into child components. Example:

class App extends Component {
    constructor(props){
        super(props);
        this.subscribers = [];
    }

    subscribe = id => { this.subscribers.push(id); }

    anyMethod(){
        // ...
        for(let fn of this.subscribers)
            fn(newId);
        // ...
    }

    render(){
        return <div>...<Browser subscribe={this.subscribe} />...</div>
    }
}

class Browser extends Component {
    constructor(props){
        super(props);
        props.subscribe(id => { this.forceLoad(id); })
    }
}

It's like API for inner component gained from Parent component :)

faiwer
  • 1,808
  • 1
  • 15
  • 17