React-router transitionTo is not a function - react-router

import React from 'react';
import { Router, Link, Navigation } from 'react-router';
export default class ResourceCard extends React.Component {
render() {
return (
<div onClick={this.routeHandler.bind(this)}>
LINK
</div>
);
}
routeHandler(){
this.transitionTo('someRoute', {objectId: 'asdf'})
}
}
I can't get it, what's wrong?
I'm receiving an error:
Uncaught TypeError: this.transitionTo is not a function
I've tried everything I've find in docs or in gitHub issues:
this.transitionTo('someRoute', {objectId: 'asdf'})
this.context.transitionTo('someRoute', {objectId: 'asdf'})
this.context.route.transitionTo('someRoute', {objectId: 'asdf'})
etc.
the route and the param is correct, it works fine in this case:
<Link to="'someRoute" params={{objectId: 'asdf}}
p.s. react-router, react and other libraries is up to date

The Navigation component is a Mixin and needs to be added to the component accordingly. If you want to bypass the Mixin (which I feel is the direction React-Router is going) you need to set the contextTypes on the component like so:
var ResourceCard = React.createClass({
contextTypes: {
router: React.PropTypes.func
}, ...
then you can call this.context.router.transitionTo.

This works with react 0.14.2 and react-router 1.0.3
import React from 'react';
import { Router, Link } from 'react-router';
export default class ResourceCard extends React.Component {
constructor(props,) {
super(props);
}
render() {
return (
<div onClick={this.routeHandler.bind(this)}>
LINK
</div>
);
}
routeHandler(){
this.props.history.pushState(null, '/');
}
}

As there's no mixin support for ES6 as of now , you need to change a few things to make it work .router is an opt-in context type so you will have to explicitly define contextTypes of the class . Then in your constructor You will have to pass context and props to super class. And while calling transitionTo you'll have to use this.context.router.transitionTo . and you don't need to import Navigation.
import React from 'react';
import { Router, Link } from 'react-router';
export default class ResourceCard extends React.Component {
constructor(props, context) {
super(props, context);
}
render() {
return (
<div onClick={this.routeHandler.bind(this)}>
LINK
</div>
);
}
routeHandler(){
this.context.router.transitionTo('someRoute', {objectId: 'asdf'})
}
}
ResourceCard.contextTypes = {
router: function contextType() {
return React.PropTypes.func.isRequired;
}
};

Related

REST calls from a react component

I'm trying to replicate same code here with different JSON, but the data is not loading.
Please help, I'm not sure what is missing in the code.
import React from 'react';
export default class ItemLister extends React.Component {
constructor() {
super();
this.state = { items: [] };
}
componentDidMount() {
fetch('http://media.astropublications.com.my/api/drebar_landing.json')
.then(result=>result.json())
.then(items=>this.setState({items}));
}
render() {
return(
<ul>
{this.state.items.length ?
this.state.items.map(item=><li key={item.id}>{item.Title}</li>)
: <li>Loading...</li>
}
</ul>
)
}
}
Your api response contains an object ArticleObject and the ArticleObject has array of objects so you need to set the items.ArticleObject to the state.
Take a look at below solution for better understanding
componentDidMount() {
fetch('http://media.astropublications.com.my/api/drebar_landing.json')
.then(result=>result.json())
.then(items=>this.setState({items:items.ArticleObject}));
}

How to create a link that goes back in react-router-dom v4

I know I can access history.goBack() to go back in the router history.
However, I'd like to create a <Link /> tag that has this functionality and relies on the to property (href) to navigate back rather than an onClick.
Is this possible?
I may have a solution to your problem using the context api.
But I strongly believe that it would be easier to use history.goBack().
First you'll need to wrap the App component inside a router:
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root'),
);
Then in your your App/index.js file you'll need to listen to the location change event and set your state accordingly:
import React, { Component } from 'react';
import { Switch, Route } from 'react-router-dom';
import { withRouter } from 'react-router'
class App extends Component {
state = { prevLocation: '' };
// Use the context api to retrieve the value in your Link
getChildContext = () => (
{
prevLocation: this.state.prevLocation,
}
);
componentWillReceiveProps(nextProps) {
if (nextProps.location !== this.props.location) {
this.setState({ prevLocation: this.props.location.pathname });
}
}
render() {
return (
<div>
<Switch>
// ...
</Switch>
</div>
);
}
}
App.childContextTypes = {
prevLocation: PropTypes.string,
};
export default withRouter(App);
Then in can create a GoBack component and use the context API to retrieve the value the previous path.
import React from 'react';
class GoBack extends React.Component {
render() {
return <Link to={this.context.prevLocation}>click</Link);
}
}
GoBack.contextTypes = {
prevLocation: PropTypes.string,
};

Testing method in react component don't work

I have simple component in React. I want to test method in this component when user click button. I have test for that but finally don't pass.
Component:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import axios from 'axios';
class TestInvokingMethod extends Component {
onClick() {
}
render() {
return (
<div>
<input id='buttonTest' type='button' value={10} onClick={this.onClick} />
</div>
);
}
}
export default TestInvokingMethod;
And test for that:
import React from 'react';
import { shallow } from 'enzyme';
import TestInvokingMethod from '../../components/TestComponent/TestInvokeMethod';
const component = shallow(
<TestInvokingMethod />
);
test('Testing invoke method', () => {
const mockFn = jest.fn();
component.instance().onClick = mockFn;
component.update();
component.find('#buttonTest').simulate('click');
expect(component.instance().onClick.mock.calls.length).toBe(1);
});
Try using Jest's SpyOn
const spy = expect.spyOn(wrapper.instance(), "onClick");
wrapper.update();
wrapper.find('#buttonTest').simulate('click');
expect(spy).toHaveBeenCalled();
In addition to Garry's answer. In scenarios where wrapper.update() does not work, try updating its instance forcefully using wrapper.instance().forceUpdate().

Is there an ES6 syntax for React-Router HOC/withRouter?

Is there a way to use the ES6 extend feature with the React-Router "withRouter" component?
Something like this:
import { withRouter } from 'react-router';
export default class extends withRouter {
...
//Use react router history prop to navigate back a page.
handleSomeEvent() {
this.props.router.goBack();
}
...
}
Or am I stuck using the old composition pattern?
var MyComponent = React.createClass({
...
});
export default withRouter(MyComponent);
Yes, it's easy, see bellow (not saying you should redirect 2s after component was mounted... just an example).
BTW my version of react-router is 2.6 (2.4+ required for withRouter)
import React, { Component } from 'react';
import { withRouter } from 'react-router';
class MyComponent extends Component {
componentDidMount() {
setTimeout(() => {
this.props.router.push('my-url')
}, 2000);
}
render() {
return (
<div>My Component</div>
);
}
}
export default withRouter(MyComponent);
You could use it like this.
#withRouter
export default class extends withRouter {
...
//Use react router history prop to navigate back a page.
handleSomeEvent() {
this.props.router.goBack();
}
...
}
But you would have to include babel-plugin-transform-decorators-legacy

RouteHandler: React.createElement: type should not be null, undefined, boolean, or number

The use of RouteHanlder gives two errors:
VM2805 bundle.js:9597Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components).
Uncaught Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
The structure of my application.
src
-- components
-- -- App.jsx
-- -- LengthModule.jsx
-- index.jsx
-- routes.js
My routes.js file
var React = require('react');
var Router = require('react-router');
var DefaultRoute = Router.DefaultRoute;
var Route = Router.Route;
var routes = (
<Route name="app" path="/" handler={require('./components/app.jsx')}>
<DefaultRoute handler={require('./components/LengthModule.jsx')} />
</Route>
)
index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App.jsx';
ReactDOM.render(<div><App /></div>, document.getElementById('app'));
App.jsx
import React from 'react';
import { Router, RouteHandler } from 'react-router';
export class App extends React.Component {
render () {
return <div>
<RouteHandler />
</div>;
}
}
LengthModule.jsx
import React from 'react';
import Router from 'react-router';
export class LengthModule extends React.Component {
render () {
return <div>"Hello World"</div>;
}
}
Am I using RouteHandler correctly? What am I missing? Are there any alternatives?
App.jsx
import React from 'react';
import { Router, RouteHandler } from 'react-router';
export default class App extends React.Component {
render () {
return <div>
<RouteHandler />
</div>;
}
}
LengthModule.jsx
import React from 'react';
import Router from 'react-router';
export defaulf class LengthModule extends React.Component {
render () {
return <div>"Hello World"</div>;
}
}
Why es6 react component works only with "export default"?
Newer tutorials warn: Be Careful About Deprecated Syntax. This article specifically mentions "<RouteHandler /> is Deprecated."