2017-10-16

Problem with Error Handling in React 16

New Error Handler in ReactJS 16 gives some great changes to how React handles JavaScript errors inside components. But I found one problem with it in case described below.

We have global script Application.jsx


export default class extends React.Component {
    render() {
        return (
          <GlobalErrorBoundary>
    <Content/>
</GlobalErrorBoundary>
        )
    }
}

(I omit import sections in my snippets to show more concise code)

GlobalErrorBoundary.jsx


export default class extends React.Component {
    constructor(props) {
        super(props);
        this.state = {error: null};
    }
    componentDidCatch(error, errorInfo) {
        this.setState({error});
    }
    render() {
        if (this.state.error) {
            return (
                <p>Global Boundary</p>
            );
        }
        return this.props.children;
    }
}

Content.jsx

const _getElement = Symbol();
export default class extends React.Component {
    render() {
        return (
            <LocalErrorBoundary>
                {this[_getElement]()}
            </LocalErrorBoundary>
        )
    }
    [_getElement]() {
        return (<div><InnerComponent/><InnerComponent2/></div>)
    }
}

LocalErrorBoundary.jsx


export default class extends React.Component {
  constructor(props) {
    super(props);
    this.state = {error: null};
  }
  componentDidCatch(error, errorInfo) {
    this.setState({error});
  }
  render() {
    if (this.state.error) {
    return (
      <p>Local Boundary</p>
    );
  }
  return this.props.children;
 }

}

Component1.jsx


const _getElement = Symbol();
export default class extends React.Component {
    render() {
        return (
            <div>
                {this[_getElement]()};
            </div>
        )
    }
    [_getElement]() {
        return 'InnerComponent1'
    }
}

Component2.jsx


const _getElement = Symbol();
export default class extends React.Component {
  render() {
    return (
      <div>
        {this[_getElement]()};
      </div>
    )
  }
  [_getElement]() {
    return 'InnerComponent2'
  }

}

And waht will happened when Content.jsx thows an error?
[_getElement]() {
        throw 500;
    }

It will be cought by 
componentDidCatch(error, errorInfo) {
        this.setState({error});
    }

and printed what we expected:
<p>Global Boundary</p>

But what happenes when we have some widget s on our page and one of them throws an error? Error will be caughed by <LocalErrorBoundary> and will be printed: 
<p>Local Boundary</p>

In many cases this is a desirable behavior, but not in my case. 
In my case, when I have many independent widgets on page and each of them gets data content from other resource (which could thow an error) this solution does not work. I’ll expect that problematic widget, which throws an error, will print error information only in its own block and Error Handling will not stop rendering other widgets.

Maybe is the other solution? I'll try to find out.

2015-05-02

Check permissions in ZF2 Zend/Navigation with ZfcRbac

ZfcRbac is not tailored to work with Zend/Navigation. There aren’t any builded native solutions that gives ZfcRbac permission to enable or disable entry of menu. The solution for that problem is quite simple.
I found solution in this blog: http://blog.webdevilopers.net/check-zend-navigation-page-permissions-with-zfcrbac/. I based on it. But this solution caused a problem. Positions in menu are displayed only if perrmision is defined. If permission is not defined, menu’s posiotin is displayed.
I’ll show you how to implement checking perrmisions and enabled / disabled menu positions with ZfcRbac. There is only one change in RbacListener:


class RbacListener
{
  protected $authorizationService;


  public function __construct(AuthorizationServiceInterface $authorizationService)
  {
      $this->authorizationService = $authorizationService;
  }


  public function accept(EventInterface $event)
  {
      $page = $event->getParam('page');


      if (! $page instanceof AbstractPage) {
          return;
      }


      $permission = $page->getPermission();


      if (is_null($permission)) {
          $event->stopPropagation();
          return false;
      }


      $event->stopPropagation();


      return $this->authorizationService->isGranted($permission);
  }
}

2015-05-01

Do not mess your code!

PHP is great language that gives us flexibility. PHP has weak typing. On the other side, many programmers abuse it. They create little monsters and spaghetti code.


In this post I will show you, on simple example, how you should prevent yourself from ambiguous return value.


Base principle: You should always return the same type.


My favorite example:


/**
* @return mixed
*/
public function getProductList()
{
   $resultArray = $this->products->get();


   return empty($resultArray) ? $resultArray : null;
}


What’s wrong with it? Return value is ambiguous. In next step in your code, after calling this method you must check what method returned to you.

if ($return === null) {
   //do something...
} else {
   //do something...
}


In this example you have two statements to check. More clear is this code:


/**
* @return array
*/
public function getProductList()
{
   $resultArray = $this->products->get();


   return $resultArray;
}

In above example, you always gets the same type of result. On the other hand, you may use designed pattern, but this is the other solution, not described in this post.