Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

javascript - Communication between Reactjs Components

After struggling too much with Redux, flux and other pub/sub methods i ended up with the following technique. I do not know if that can cause some big damage or flaws so posting it here to get some light from the experienced programmers about its pros and cons.

var thisManager = function(){

    var _Manager = [];
    return{
        getThis : function(key){
            return  _Manager[key];
        },
        setThis : function(obj){            
            _Manager[obj.key] = obj.value;
        }
    }
};
var _thisManager = new thisManager();

// React Component
class Header extends Component{
   constructor(){
      super();
      _thisManager.setThis({ key: "Header", value:this}
   }
    someFunction(data){
        // call this.setState here with new data. 
   }
   render(){
      return <div />
   }
}

// Then from any other component living far somewhere you can pass the data to the render function and it works out of the box. 
i.e. 

class Footer extends Component{
  _click(e){
     let Header = _thisManager.getThis('Header');
     Header.somefunction(" Wow some new data from footer event ");
  }
 render(){
      return(
      <div>
          <button onClick={this._click.bind(this)}> send data to header and call its render </button>
      </div>


      );
  }
}

I am sending json as a data in my application and it perfectly renders the desired components and i can invoke the render without any pub/sub or deep passing down the props to invoke a parent method with a changing this.setState to cause re-render.

So far the application works fine and i am also loving its simplicity too. Kindly throw light on this technique pros and cons

Regards

EDIT:

It is bad to call render so i changed it to another method to get more pros and cons of this setup.

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

Two main concerns with this setup:
1. You should never call react lifecycle methods directly
2. Backdoors into components are a bad idea, which destroy react's maintainability

Ad 1: If you invoke render() (or any other react method) directly, react probably does not call componentDidMount(), componentDidUpdate()` and other lifecycle methods in the component tree.

Dangers are:

  • Many designs with react component rely heavily on the lifecycle methods being fired: getInitialState(), componentWillReceiveProps(), shouldComponentUpdate(), componentDidMount(), etc etc. If you call render() directly, many components will likely break or show strange behaviour.
  • You run the risk of breaking react's difference engine: through life-cycle management, react keeps a virtual copy of DOM in its (internal) memory. To work correctly, the integrity of this copy if vital to react's working.

Better would be (but still in violation of my second point):

  • Include a different method inside the component.
  • Which has a setState() if you want to re-render.
  • And call that method from the outside.

Ad 2. A direct reference to a mounted component (as your thisManager does) has some additional risks. React's designs and limitations are there for a reason: to maintain unidirectional flow and component hierarchy with props and state, to make things easy to maintain.

If you break this pattern - by building a backdoor into a component, which allows manipulation of state - you break this design principle of react. It is a quick shortcut, but is sure to cause great pain and frustation when your app grows.

As far as I know, the only acceptable exceptions to this rule are:

  • Methods inside a component that respond to ajax call results, to update state (e.g. after fetching data from server)
  • Methods inside a component to handle triggers from its direct descendent children components (e.g. run validation on form after a child button has been clicked)

So if you want to use it for that purpose, then you should be fine. Word of warning: the standard react approach guards random access to components, because the invoking component or method needs to have a reference to the component. In both examples such a reference is available.
In your setup, ANY outside piece of code could lookup the ref to the "header" in your table, and call the method which updates state. With such indirect reference, and no way of telling which source actually called your component, your code is likely to become much harder to debug/ maintain.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...