are ownProps passed to component by default? - reactjs

i have below snippet.
AnotherFile.js
import MyAccount from './MyAccount';
<MyAccount name='peace and love' />
MyAccount.js
const MyAccount = (props) => {
// I can access props.isLoggedIn and props.setLogout,
// and I can access props.name too, wow
}
const mapStateToProps = (state) => ({
isLoggedIn: state.isLoggedIn
})
const mapDispatchToProps = dispatch => ({
setLogout: () => dispatch(setLogout())
})
export default connect(mapStateToProps, mapDispatchToProps)(MyAccount)
So I pass some props to the connected components, and the presentational component MyAccount can access these props too.
Previously, if I intend to achieve that, I would add a second argument in mapStateToProps, like below. But now it seems it is unnecessary to pass ownProps? Can someone confirm please?
const mapStateToProps = (state, ownProps) => ({
isLoggedIn: state.isLoggedIn,
...ownProps
})

From the react-redux docs:
ownProps (optional)
[...]
You do not need to include values from ownProps in the object returned from mapStateToProps. connect will automatically merge those different prop sources into a final set of props.
So yes, it is unnecessary to explicitly spread ownProps into the props returned by mapStateToProps.
You usually only need ownProps if your component needs the data from its own props to retrieve data from the store, e.g. using an id prop to select a certain item from a list of items.

Related

Using component prop inside function body of reselect?

Honestly, after hours of research, I totally don't understand reselect, so I just ask why I need it, and if it can help.
Selectors are efficient. A selector is not recomputed unless one of its arguments changes.
It's a bit unclear, what do we mean as argument here, but I assume that not the redux state, because otherwise there wouldn't be any point in reselect.
My goal is to not calculate the whole list every time something happens, because it can contain thousands of elements.
First question is that if for an example the value of state["2"] changes to 4 for an example, it will run through the whole list?
//for an example, in the next list, the key is the child,
//and the value is it's parent
const state = {
1: 5,
2: 5,
3: 2,
4: 1,
5: 10,
//...
1000: 342
};
//and we have to find all children of a specific element,
//what we get from the component's own props
const getState = (
state,
props //okay, I can access it here
) => state;
const getChildren = createSelector(
[getState],
state => Object.keys(state).filter(child => {
const parent = state[child];
return parent === props.id //but I need it here
})
);
const mapStateToProps = (state, props) = ({ children: getChildren(state, props) });
And the main question: how can I access the props inside the function body?
You can pass the props argument directly to the other selector getChildren and you don't need the first getState like this:
const getChildren = createSelector(
[
state => state,
props => props
], (state, props) => {...}
About clarifying the use cases for reselect:
it does recompute if the state or the props changes (any argument indeed). So why using it? I use it for 2 reasons
you can combine parts of state coming from multiple reducers and build up what we can call a 'meta-reducer' and pass that to your component. In that way you place that code only in one place (the selector) and you can reuse it across different components. Imagine each reducer like a database table and the selector like a query result. You can query anything from your state and you want to keep the result cached for performance.
instead of running this logic on the mapStateToProps which is run every time that a component renders (no matter if the state has changed), you run it only 1 time per state change and you get the cached version if the component rerenders. This happens for example if a child component renders only because its parent rendered but the state portion related to its selector didn't change. So I like to use selectors all the times instead of accessing the redux state directly.
Here's the typical flow.
You'll have some ConnectedComponent that's hooked into connect, and its mapStateToProps calls out to a selector with both state and ownProps.
You have individual selectors for both the getting of id off of props and your objects from state.
Using ConnectedComponent
<span>
<ConnectedComponent id="123" />
</span>
mapStateToProps (ConnectedComponent)
import {connect} from 'react-redux'
import {getMyObjectSelector} from './selectors';
const mapStateToProps = (state, ownProps) => ({
myObject: getMyObjectSelector(state, ownProps)
});
export default connect(mapStateToProps)(Component)
selectors
const getIdFromProps = (state, props) => props.id
const getMyObjectsFromState= state => state.myObjects;
export getMyObjectSelector = createSelector(
getMyObjectsFromState,
getIdFromProps,
(objects, id) => objects[id]
);
Component
export const Component = ({myObject}) => (
<span>
// Do stuff
</span>
)

Defining mapDispatchToProps As An Object

I am just wondering for Defining mapDispatchToProps As An Object how can I pass ownProps to it? like in the function I can pass props as an argument.
const mapDispatchToProps = (dispatch, ownProps) => {
toggleTodo: () => dispatch(toggleTodo(ownProps.todoId));
};
for an object how to pass ownProps?
const mapDispatchToProps = {
toggleTodo
};
My account got blocked by some down votes questions, the funny thing is I have to re-edit them, even though I already have the accepted answer.I do not understand what's the point to do this.I am so frustrated by this stackoverflow system.
Now, I basically can do nothing but keep editing my questions, and they have all been answered. This is ridiculous !!!
Short answer: You dont need to. You pass the props into each action as they are called and needed.
Long answer:
mapDispatchToProps connects your actions to dispatch in the component so you can call the action and pass in required props for it using this.props.action instead of awkwardly finding dispatch and using this.props.dispatch(action()) or similar.
I find it's simpler to connect your actions to your export and call the action this.props.addUser(prop1,prop2) when needed - onClick(), componentDidMount() etc. It by default assigns dispatch to it without needing to do mapDispatchToProps. So
export default connect(
mapStateToProps,
{action1, action2, addUser})(User)
then you can use:
addNewUser = () => {
this.props.addUser(this.state.person);
}
where you pass in the props you're after and then do any other work the action or reducer itself (depending on your preference of flow) such as:
export const addUser = user => ({
type: ADD_USER_SUCCESS,
payload: {user}
})
ownProps can't be passed to it without doing the wiring in mergeProps function passed in the connect function.
You see, when mapDispatchToProps is an object, whenMapDispatchToPropsIsObject is invoked. It in turn invokes wrapMapToPropsConstant which does this
constantSelector.dependsOnOwnProps = false
Now, this property is used to decide whether the action dispatcher should be invoked with props or not. See all handle* functions like handleNewPropsAndNewState in src/connect/selectorFactory.js
This is in contrast with what happens when mapDispatchToProps is a function. In this case, wrapMapToPropsFunc when invoked wraps the action dispatcher and then invokes it with props.
Without passing mergeProps, you'll need to forward id prop to the action creator in the Component that is connected with the mapDispatchToProp
e.g.
onClickToggleButton = () => {
const {id, toggleTodo} = this.props
toggleTodo(id)
}

mapStateToProps vs mapDispatchToProps [duplicate]

This question already has answers here:
What is mapDispatchToProps?
(6 answers)
Closed 4 years ago.
What's the difference between mapStateToProps and mapDispatchToProps arguments to the connect function in react-redux?
mapStateToProps is a function that you would use to provide the store data to your component, whereas mapDispatchToProps is something that you will use to provide the action creators as props to your component.
According to the docs:
If mapStateToProps argument is specified, the new component will
subscribe to Redux store updates. This means that any time the store
is updated, mapStateToProps will be called. The results of
mapStateToProps must be a plain object, which will be merged into
the component’s props.
With mapDispatchToProps every action creator wrapped into a dispatch
call so they may be invoked directly, will be merged into the
component’s props.
A simple example would be
function mapStateToProps(state) {
return { todos: state.todos }
}
function mapDispatchToProps(dispatch) {
return { addTodo: bindActionCreators(addTodo, dispatch) }
}
export default connect(mapStateToProps, mapDispatchToProps)(Todos);
In a very simple term,
mapStateToProps: It connects redux state to props of react component.
mapDispatchToProps: It connects redux actions to react props.
A really light example: ( I hope, you know what I mean)
// state
const mapStateToProps = state => {
return { lists: state.lists };
};
// props
const mapDispatchToProps = ({ lists }) => (
<ul>
{
lists.map(el => (
<li key={ el.id }>
{ el.heading }
</li>
)
}
</ul>
);
// Now, connect state to prop
const List = connect(mapStateToProps)(mapDispatchToProps);
In very simple terms:
mapStateToProps is called when you want to get the value of the global state from your component
function mapStateToProps(state) {
return {
message: state.message
};
}
The value of the global state is only changed with the help of an action. So if you want to change the value of global state you need an action. mapDispatchToProps is used to bind action in your component.

What is mapDispatchToProps?

I was reading the documentation for the Redux library and it has this example:
In addition to reading the state, container components can dispatch actions. In a similar fashion, you can define a function called mapDispatchToProps() that receives the dispatch() method and returns callback props that you want to inject into the presentational component.
This actually makes no sense. Why do you need mapDispatchToProps when you already have mapStateToProps?
They also provide this handy code sample:
const mapDispatchToProps = (dispatch) => {
return {
onTodoClick: (id) => {
dispatch(toggleTodo(id))
}
}
}
What is this function and why it is useful?
I feel like none of the answers have crystallized why mapDispatchToProps is useful.
This can really only be answered in the context of the container-component pattern, which I found best understood by first reading:Container Components then Usage with React.
In a nutshell, your components are supposed to be concerned only with displaying stuff. The only place they are supposed to get information from is their props.
Separated from "displaying stuff" (components) is:
how you get the stuff to display,
and how you handle events.
That is what containers are for.
Therefore, a "well designed" component in the pattern look like this:
class FancyAlerter extends Component {
sendAlert = () => {
this.props.sendTheAlert()
}
render() {
<div>
<h1>Today's Fancy Alert is {this.props.fancyInfo}</h1>
<Button onClick={sendAlert}/>
</div>
}
}
See how this component gets the info it displays from props (which came from the redux store via mapStateToProps) and it also gets its action function from its props: sendTheAlert().
That's where mapDispatchToProps comes in: in the corresponding container
// FancyButtonContainer.js
function mapDispatchToProps(dispatch) {
return({
sendTheAlert: () => {dispatch(ALERT_ACTION)}
})
}
function mapStateToProps(state) {
return({fancyInfo: "Fancy this:" + state.currentFunnyString})
}
export const FancyButtonContainer = connect(
mapStateToProps, mapDispatchToProps)(
FancyAlerter
)
I wonder if you can see, now that it's the container 1 that knows about redux and dispatch and store and state and ... stuff.
The component in the pattern, FancyAlerter, which does the rendering doesn't need to know about any of that stuff: it gets its method to call at onClick of the button, via its props.
And ... mapDispatchToProps was the useful means that redux provides to let the container easily pass that function into the wrapped component on its props.
All this looks very like the todo example in docs, and another answer here, but I have tried to cast it in the light of the pattern to emphasize why.
(Note: you can't use mapStateToProps for the same purpose as mapDispatchToProps for the basic reason that you don't have access to dispatch inside mapStateToProp. So you couldn't use mapStateToProps to give the wrapped component a method that uses dispatch.
I don't know why they chose to break it into two mapping functions - it might have been tidier to have mapToProps(state, dispatch, props) IE one function to do both!
1 Note that I deliberately explicitly named the container FancyButtonContainer, to highlight that it is a "thing" - the identity (and hence existence!) of the container as "a thing" is sometimes lost in the shorthand
export default connect(...)
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
syntax that is shown in most examples
It's basically a shorthand. So instead of having to write:
this.props.dispatch(toggleTodo(id));
You would use mapDispatchToProps as shown in your example code, and then elsewhere write:
this.props.onTodoClick(id);
or more likely in this case, you'd have that as the event handler:
<MyComponent onClick={this.props.onTodoClick} />
There's a helpful video by Dan Abramov on this here:
Redux: Generating Containers with connect() from React Redux (VisibleTodoList)
mapStateToProps() is a utility which helps your component get updated state(which is updated by some other components),
mapDispatchToProps() is a utility which will help your component to fire an action event (dispatching action which may cause change of application state)
mapStateToProps, mapDispatchToProps and connect from react-redux library provides a convenient way to access your state and dispatch function of your store. So basically connect is a higher order component, you can also think as a wrapper if this make sense for you. So every time your state is changed mapStateToProps will be called with your new state and subsequently as you props update component will run render function to render your component in browser. mapDispatchToProps also stores key-values on the props of your component, usually they take a form of a function. In such way you can trigger state change from your component onClick, onChange events.
From docs:
const TodoListComponent = ({ todos, onTodoClick }) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
)
const mapStateToProps = (state) => {
return {
todos: getVisibleTodos(state.todos, state.visibilityFilter)
}
}
const mapDispatchToProps = (dispatch) => {
return {
onTodoClick: (id) => {
dispatch(toggleTodo(id))
}
}
}
function toggleTodo(index) {
return { type: TOGGLE_TODO, index }
}
const TodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
Also make sure that you are familiar with React stateless functions and Higher-Order Components
Now suppose there is an action for redux as:
export function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
When you do import it,
import {addTodo} from './actions';
class Greeting extends React.Component {
handleOnClick = () => {
this.props.onTodoClick(); // This prop acts as key to callback prop for mapDispatchToProps
}
render() {
return <button onClick={this.handleOnClick}>Hello Redux</button>;
}
}
const mapDispatchToProps = dispatch => {
return {
onTodoClick: () => { // handles onTodoClick prop's call here
dispatch(addTodo())
}
}
}
export default connect(
null,
mapDispatchToProps
)(Greeting);
As function name says mapDispatchToProps(), map dispatch action to props(our component's props)
So prop onTodoClick is a key to mapDispatchToProps function which delegates furthere to dispatch action addTodo.
Also if you want to trim the code and bypass manual implementation, then you can do this,
import {addTodo} from './actions';
class Greeting extends React.Component {
handleOnClick = () => {
this.props.addTodo();
}
render() {
return <button onClick={this.handleOnClick}>Hello Redux</button>;
}
}
export default connect(
null,
{addTodo}
)(Greeting);
Which exactly means
const mapDispatchToProps = dispatch => {
return {
addTodo: () => {
dispatch(addTodo())
}
}
}
mapStateToProps receives the state and props and allows you to extract props from the state to pass to the component.
mapDispatchToProps receives dispatch and props and is meant for you to bind action creators to dispatch so when you execute the resulting function the action gets dispatched.
I find this only saves you from having to do dispatch(actionCreator()) within your component thus making it a bit easier to read.
React redux: connect: Arguments

Passing props to react-redux container component

I have a react-redux container component that is created within a React Native Navigator component. I want to be able to pass the navigator as a prop to this container component so that after a button is pressed inside its presentational component, it can push an object onto the navigator stack.
I want to do this without needing to hand write all the boilerplate code that the react-redux container component gives me (and also not miss out on all the optimisations that react-redux would give me here too).
Example container component code:
const mapStateToProps = (state) => {
return {
prop1: state.prop1,
prop2: state.prop2
}
}
const mapDispatchToProps = (dispatch) => {
return {
onSearchPressed: (e) => {
dispatch(submitSearch(navigator)) // This is where I want to use the injected navigator
}
}
}
const SearchViewContainer = connect(
mapStateToProps,
mapDispatchToProps
)(SearchView)
export default SearchViewContainer
And I'd want to be able to call the component like this from within my navigator renderScene function:
<SearchViewContainer navigator={navigator}/>
In the container code above, I'd need to be able to access this passed prop from within the mapDispatchToProps function.
I don't fancy storing the navigator on the redux state object and don't want to pass the prop down to the presentational component.
Is there a way I can pass in a prop to this container component? Alternatively, are there any alternative approaches that I'm overlooking?
Thanks.
mapStateToProps and mapDispatchToProps both take ownProps as the second argument.
[mapStateToProps(state, [ownProps]): stateProps] (Function):
[mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function):
For reference
You can pass in a second argument to mapStateToProps(state, ownProps) which will give you access to the props passed into the component in mapStateToProps
There's a few gotchas when doing this with typescript, so here's an example.
One gotcha was when you are only using dispatchToProps (and not mapping any state props), it's important to not omit the state param, (it can be named with an underscore prefix).
Another gotcha was that the ownProps param had to be typed using an interface containing only the passed props - this can be achieved by splitting your props interface into two interfaces, e.g.
interface MyComponentOwnProps {
value: number;
}
interface MyComponentConnectedProps {
someAction: (x: number) => void;
}
export class MyComponent extends React.Component<
MyComponentOwnProps & MyComponentConnectedProps
> {
....// component logic
}
const mapStateToProps = (
_state: AppState,
ownProps: MyComponentOwnProps,
) => ({
value: ownProps.value,
});
const mapDispatchToProps = {
someAction,
};
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
The component can be declared by passing the single parameter:
<MyComponent value={event} />
Using Decorators (#)
If you are using decorators, the code below give an example in the case you want to use decorators for your redux connect.
#connect(
(state, ownProps) => {
return {
Foo: ownProps.Foo,
}
}
)
export default class Bar extends React.Component {
If you now check this.props.Foo you will see the prop that was added from where the Bar component was used.
<Bar Foo={'Baz'} />
In this case this.props.Foo will be the string 'Baz'
Hope this clarifies some things.

Resources