How to extract an URL segment in React - reactjs

I have inherited a project and are very new to React.
The problem is that I don't know how to extract an URL segment like 123456 from the URL page/123456.
Here is some code for I sidebar I want to use the URL segment in. I kept it short so it is as clear as possible where I want the URL segment.
import React, { Component } from 'react';
import { withRouter, Link } from 'react-router-dom';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { push } from 'connected-react-router';
class Sidebar extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
URL segment:
</div>
);
}
}
export default compose(withRouter))(Sidebar);

If you have a router configured properly then you might be able to find that value as a string in the this.props.match.params. You can take a look to the following example(please note that it's using react hooks and the main difference for you would be to use this.props.match.params instead of useParams()).
P.S. you should call withRouter instead of passing it to the compose method. E.g. withRouter(Sidebar) and if you want to use it with connect I guess you can just call one inside the other: connect(...)(withRouter(Sidebar))

Related

How to change header background color in react based on location

How do I change my headers color based on what route/page I am on in my React project?
I have looked at withRouter but I am not sure how to use the example.
I just want to do something like if the route is not the Home component then change the background color of the header to blue. Seems like it would be simple but can't figure it out.
You can use the location prop that is added to your component by connecting the component to the router via withRouter. From there you apply a conditional style based on which route path you are in.
import React from 'react'
import PropTypes from 'prop-types'
import { withRouter } from 'react-router'
// A simple component that shows the pathname of the current location
class Header extends React.Component {
static propTypes = {
match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired
}
render() {
const { match, location, history } = this.props
const headerColor = location.pathname === 'home' ? { background: 'white'} : { background: 'blue' }
return (
<div style={headerColor}>You are now at {location.pathname}</div>
)
}
}
// Create a new component that is "connected" (to borrow redux
// terminology) to the router.
const AdaptiveHeader = withRouter(Header)
export default AdaptiveHeader
For the above example I repurposed the code found here.
You can use this.props.location from withRouter to get the current pathname. Use that to check against /home or whatever your home page is, and then you can add a class to the Header that changes the color.

Why creating a new Component class for redux connect?

In reference this coding pattern:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Thing from '../components/Thing';
class ThingContainer extends Component {
render() {
return <Thing {...this.props} />;
}
}
function mapStateToProps(state) {
...
}
export default connect(mapStateToProps)(ThingContainer);
So it 1) imports a component(Thing), 2) creates another component (ThingContainer which is technically not a container) class to render that first component, and lastly using connect to finally export the container.
What's the difference with skipping step 2 above, and simply using the imported component(Thing) directly to export the container?
Yeah, that file looks like it's somewhat unnecessary. The class ThingContainer component does nothing but forward props to <Thing>, which is exactly what the wrapper components generated by connect do already. So, that's useless - the file should just do export default connect(mapState)(Thing), and it would work exactly the same without the extra ThingContainer definition.

ES6, React, Redux forms. Trying to do something simple

G'day, I am trying to do something simple, and cant get a hold of it.
I have a number of forms. A LOT of forms. To keep my API succinct on the client I want to pass two state values into my client API.
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import { Link, browserHistory } from 'react-router';
import { apiCreateData } from '../actions/api';
import { CREATE_PERSON } from '../actions/api';
import _ from 'lodash';
The apiCreateData is a generic client side API which needs to simply call a server API with the form contents, a TARGET URI of the server REST API, and a constant "which type of action is going on".
//------------------------------------
class CreatePeople extends Component {
//------------------
constructor(props) {
super(props);
this.state = {
target: 'add_person',
type: CREATE_PERSON
};
}
I can see these in my REACT tools in Chrome. The 'go' button calls this code.
//----------------------
onSubmit = (fields) => {
console.log('onSubmit');
console.log(fields);
this.props.apiCreateData(...this.state, fields).then(() => {
browserHistory.push('/');
});
}
I can not get those two bits of state into the receiving props in the client API. I tried heaps of stuff! Any help appreciated.
Cheers,
Mark.

dispatch is not a function

I am trying to add the redux-file-upload library into a redux application.
In my component I am just adding the component exported from the lib.
I can see that the store is referred via context inside the library.
Sample code is as below,
import React, { Component } from 'react';
import { FileUpload } from 'redux-file-upload';
class Upload extends Component {
render() {
return (
<FileUpload
allowedFileTypes={['jpg', 'pdf']}
dropzoneId="fileUpload"
url="/api/path/action"
>
<button> Drag or click here
</button>
</FileUpload>
);
}
}
export default Upload;
However I get error as
Uncaught TypeError: dispatch is not a function
Any ideas? Guess it is some mistake in importing the component.
Uncaught TypeError: dispatch is not a function
I have come across this error many times for different reasons. I can't dive into the source code of that library, but it looks like that library is not able to get dispatch function from the redux store. Have you tried connecting your component to the redux store using connect() method? It's a long shot. Thought, it might work! Let me know...
UPDATE
I'm throwing related links here, hoping that you'd find the relevant piece of code.
https://github.com/reactjs/react-redux/issues/108
React with Redux? What about the 'context' issue?
https://github.com/reactjs/react-redux/issues/108
You need import 'redux-form' , your code should be like this...
import React, { Component } from 'react';
import { FileUpload } from 'redux-file-upload';
import {reduxForm} from 'redux-form';
class UploadForm extends Component {
render() {
return (
<FileUpload
allowedFileTypes={['jpg', 'pdf']}
dropzoneId="fileUpload"
url="/api/path/action"
>
<button> Drag or click here
</button>
</FileUpload>
);
}
}
export default reduxForm({
form: 'upload-form',
fields: ['fileUpload']
})(UploadForm);
Are you using a middleware with you store, like redux-thunk/redux-promise?
The library you are using requires it:
"Please note - a middleware that passes dispatch to actions, e.g.
redux-thunk, redux-promise-middleware, is required for this package to
work properly."
So if you are using react-redux and the Provider yuo can do the following:
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import promise from 'redux-promise'
const storeWithMiddleware = applyMiddleware(promise)(createStore);

React Router Redux go action is shown in the LogMonitor but doesn't change the path on browser

I'm using react-redux-starter-kit on one of my views I just want to redirects users is somethig is not set My components is fairly simple
// MyComponentWithRedirect.js
import React, {Component, PropTypes} from 'react'
import {connect} from 'react-redux'
import {go} from 'react-router-redux'
class MyComponentWithRedirect extends Component {
static propTypes = {
userInfo: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired
}
componentDidMount() {
if (this.props.userInfo.firstTime) {
this.props.dispatch(go('/welcome'))
}
}
}
const mapStateToProps = (state) => ({userInfo: state.userInfo})
export default connect(mapStateToProps)(MyComponentWithRedirect)
I can see the LOCATION_CHANGE action triggered but doesn't show the destination view
I've found I missed the setup of syncHistoryWithStore after that it's works like a charm using the react-router API
import { browserHistory } from 'react-router'
...
browserHistory.push('/welcome')
I dont need dispatch any more for change the location

Resources