Passing props from Redux - javascript

How to call props from redux without passing props from the parent component.
...
<Component name={name}/>
...
I want use props.something() here
const Component = (name) => {
//how to call props here?
//ex : props.something()
}
export default connect(mapStateToProps,mapDispatchToProps)(Component)

The props are passed as functional component's arguments:
const Component = (props) => {
// props.name
}
Or you can use Destructuring syntax:
const Component = ({name}) => {
// name
}

Also you can destructure more than one items from props.
<MyComponent name={name} title={title} description={description} />
const MyComponent = ({ name, title, description )} => {
// ...
}
export default MyComponent;

Related

How to pass props from parent to child in react?

I've been refactoring a small application that was initially within one file into it's own separate components. Currently I have a child component UsersTable that I am rendering within the parent Users2. I am passing some dummy data from the parent as props to the child but am getting the lovely Cannot read property 'map' of undefined.
I am using react hooks and passing props with the spread operator in the parent:
<UsersTable {...columns} {...data} />
And the child is receiving that here:
export const UsersTable = props => {
const [usersState, setUsersState] = useState(props)
useEffect(() => {
setUsersState(props)
}, [props])
const renderUsers = () => {
if (usersState) {
return usersState.map(d => items(d))
} else {
return noData
}
}
As well as down in the return function here:
<ActionList columns={usersState}>{renderUsers}</ActionList>
I am specifically trying to figure out why the data prop (an array of objects), is returning undefined. Linking my sandbox here. I wondering if the issue is perhaps related to passing multiple separate props via spread operators.
Any help or advice around what I am trying to accomplish would be much appreciated!
That's not a correct way to pass down props.
Props are passed as properties of an object and hence you need to define a name and value to it.
For ex, you need to write,
<UsersTable {...columns} {...data} />
as
<UsersTable columns={columns} data = {data} />
Now the UserTable component will get this props object,
props = {
columns=the column data,
data = the data
}
To use this props, you can use destructuring
const {data, columns} = props;
or you can use the dot notation,
props.column & props.data
You need to pass by attribute
<UsersTable columns={...columns} data={...data} /> /*<-- Changes */
export const UsersTable = props => {
const [usersState, setUsersState] = useState(props)
useEffect(() => {
setUsersState(props)
}, [props])
const renderUsers = () => {
if (usersState) {
return usersState.map(d => items(d))
} else {
return noData
}
}
<ActionList columns={usersState}>{renderUsers}</ActionList>
In User2 component, import UsersTable component need change from this:
<UsersTable {...columns} {...data} />
to this:
<UsersTable columns={columns} data={data} />
And in UserTable component you need to change:
const [usersState, setUsersState] = useState(props)
to:
const [columns, setColumns] = useState(props.columns)
const [users, setUsers] = useState(props.data)
renderUsers will be:
const renderUsers = () => {
if (users) {
return users.map(d => items(d))
} else {
return noData()
}
}
And last, import ActionList component like this:
<ActionList columns={columns}>{renderUsers()}</ActionList>
After that, UsersTable component will working fine.
Parent Component:
<UsersTable columns={columns} data={data} />
See my github for an example of how to use hooks and props in a similar way:
https://github.com/RyanJMorris11/helloReactHooks/blob/master/src/components/userList.js

How do I pass a React prop from Parent to Child, to another Child?

I currently have my Parent set up as follows, which I'm then passing props to
class WorkoutPlan extends React.Component {
constructor() {
super();
this.state = {
workoutPlan: {}
};
}
componentDidMount() {
axios
.get("/api/workout-plan")
.then(response => {
this.setState({ workoutPlan: response.data });
})
.catch(error => {
console.log(error);
});
}
render() {
const { workoutPlan } = this.state;
// const workoutPlan = this.state.workoutPlan;
return (
<div>
<h1>{workoutPlan.Name}</h1>
<button className="button" onClick={this.handleClick}>
Click Me
</button>
<Workout {...workoutPlan.workout} />
</div>
);
}
}
Then in my child, I'm wanting to pass those same props to another Child
import React from "react";
import Exercise from "./Exercise";
const Workout = props => {
return (
<div>
<h2>"Workout for {props.day}"</h2>
<Exercise {...workoutPlan.workout} />
</div>
);
};
export default Workout;
I can't seem to figure out how I would go about doing this. I'm being told that the setup is exactly the same as the 1st child, but when I enter in the same code, it's not working.
You can pass {...props} to your Exercise component so your Workout component should look like this
import React from "react";
import Exercise from "./Exercise";
const Workout = props => {
return (
<div>
<h2>"Workout for {props.day}"</h2>
<Exercise {...props} />
</div>
);
};
export default Workout;
When you pass props destructuring it, the effect it's the same as you were passing props one by one.
You can't achieve your goal because in your Workout component there is no "workout" prop.
Try to pass props to Exercise component like this:
<Exercise {...props} />

Warning: Functions are not valid as a React child HOC

I'm writing an HOC in Reactjs. When I'm going to return class in WithErrorHandler HOC I get a warning in console said
"Functions are not valid as a React child. This may happen if you
return a Component instead of <Component /> from render. Or maybe you
meant to call this function rather than return it." However, if I
remove class, warning will be gone.
I am going to add click handler for Modal to enable it to close. Also, I am going to get message from error which I have passed as an argument of second function for show in Modal.
import React, { Component } from 'react';
import Modal from '../Modal'
const WithErrorHandler = WrappedComponent => ({ error, children }) => {
return(
class extends Component {
state = {modalShow: false}
modalToggle = ()=> {
this.setState(ModalShow: !!error.message)}
render() {
return (
<WrappedComponent>
{error && <Modal type={error.messageType} message={error.message} />}
{children}
</WrappedComponent>
);
}
}
)
};
const DivWithErrorHandling = WithErrorHandler(({children}) => {
return children
})
class App extends Component {
state ={error: null}
someMethode = ()=> {
const sampleError = {//an object with message key}
this.setState(error: sampleError)
}
Render(){
return (
<DivWithErrorHandling error={this.state.error} >
<h1>Component</h1>
<button onClick={this.someMethode}>
Toggle Error
</button>
</DivWithErrorHandling>
)
}
}
Your HOC is accepting actual component & returning a children function(wrapper component) which again returns a class component.
Instead of that your HOC should accept actual component & return a new wrapped component.
This should probably fix your issue.
const WithErrorHandler = WrappedComponent => ({ error, children }) => {
return(
<WrappedComponent>
{error && <Modal type={error.messageType} message={error.message} />}
{children}
</WrappedComponent>
);
};
HOC is a function that takes a component and returns a new component
Your code:
const WithErrorHandler
= WrappedComponent // takes a component
=> ({ error, children }) // takes some params
=> class ... // returns a new component
What you actually want:
const WithErrorHandler
= WrappedComponent // takes a component
=> class ... // returns a new component
// inside the class use this.props.error, this.props.children, etc.
Another way (using a functional component):
const WithErrorHandler
= WrappedComponent // takes a component
=> ({ error, children }) => <WrappedComponent>...</WrappedComponent> // returns a new component

passing all props with class and stateless component

Are those 2 components below identical? What is the purpose is I'm trying to do a wrapper to customize a component.
does
const myComponent = (props) => {
return (
<OtherComponent {...props} />
)
}
and
class myComponent extends Component {
const { ...rest } = this.props
render() {
return <OtherComponent {...rest} />
}
}
{...props}
identical to
const { ...rest } = this.props
?
Yes, both ways of writing it are identical. Every key/value pair in this.props will end up in the rest variable.
Instead of writing const { ...rest } = this.props you can use this.props directly instead.
const MyComponent1 = (props) => {
return (
<OtherComponent {...props} />
)
}
class MyComponent2 extends Component {
render() {
return <OtherComponent {...this.props} />
}
}
Yes, they are identical. At first {...props} is the use of spread operator to copy the props object and pass it to the other component.
In case of const {...rest} = this.props, spread operator is used with Destructuring assignment. Destructuring syntax allows to extract or unpack objects or arrays into bunch of variables.
Code:
let obj={a:"1",b:"2",c:"3"}
let {a,...rest}=obj
console.log(a)
console.log(rest)
Output:
1
{b:"2",c:"3"}
Here, a is extracted from obj and is assigned to variable named a and rest of the object is assigned to variable named rest.
So it means doing const {..rest} = this.props and passing it to the other component results the same as doing {...props}.
There are two types of components in react
Stateless Component or Functional component
const myComponent = (props) => {
return (
<OtherComponent {...props} />
)
}
Job of this component is to just render pure jsx!
Stateful component or Class Component
`
class myComponent extends Component {
const { ...rest } = this.props
render() {
return <OtherComponent {...rest} />
}
}
`
Class components offer more features, and with more features comes more baggage. The primary reason to choose class components over functional components is that they can have state and lifecycle hooks with them such as componentWillMount(), componentDidUpdate()
So, to conclude if we want to render a component who is receiving props from its parent and no manipulation is to be done within their state then we can go for functional component
and about your second question
{...props} is identical to const { ...rest } = this.props
yes, it's identical!
Hope this helps !

React: Passing props to function components

I have a seemingly trivial question about props and function components. Basically, I have a container component which renders a Modal component upon state change which is triggered by user click on a button. The modal is a stateless function component that houses some input fields which need to connect to functions living inside the container component.
My question: How can I use the functions living inside the parent component to change state while the user is interacting with form fields inside the stateless Modal component? Am I passing down props incorrectly?
Container
export default class LookupForm extends Component {
constructor(props) {
super(props);
this.state = {
showModal: false
};
}
render() {
let close = () => this.setState({ showModal: false });
return (
... // other JSX syntax
<CreateProfile fields={this.props} show={this.state.showModal} onHide={close} />
);
}
firstNameChange(e) {
Actions.firstNameChange(e.target.value);
}
};
Function (Modal) Component
const CreateProfile = ({ fields }) => {
console.log(fields);
return (
... // other JSX syntax
<Modal.Body>
<Panel>
<div className="entry-form">
<FormGroup>
<ControlLabel>First Name</ControlLabel>
<FormControl type="text"
onChange={fields.firstNameChange} placeholder="Jane"
/>
</FormGroup>
);
};
Example: say I want to call this.firstNameChange from within the Modal component. I guess the "destructuring" syntax of passing props to a function component has got me a bit confused. i.e:
const SomeComponent = ({ someProps }) = > { // ... };
You would need to pass down each prop individually for each function that you needed to call
<CreateProfile
onFirstNameChange={this.firstNameChange}
onHide={close}
show={this.state.showModal}
/>
and then in the CreateProfile component you can either do
const CreateProfile = ({onFirstNameChange, onHide, show }) => {...}
with destructuring it will assign the matching property names/values to the passed in variables. The names just have to match with the properties
or just do
const CreateProfile = (props) => {...}
and in each place call props.onHide or whatever prop you are trying to access.
I'm using react function component
In parent component first pass the props like below shown
import React, { useState } from 'react';
import './App.css';
import Todo from './components/Todo'
function App() {
const [todos, setTodos] = useState([
{
id: 1,
title: 'This is first list'
},
{
id: 2,
title: 'This is second list'
},
{
id: 3,
title: 'This is third list'
},
]);
return (
<div className="App">
<h1></h1>
<Todo todos={todos}/> //This is how i'm passing props in parent component
</div>
);
}
export default App;
Then use the props in child component like below shown
function Todo(props) {
return (
<div>
{props.todos.map(todo => { // using props in child component and looping
return (
<h1>{todo.title}</h1>
)
})}
</div>
);
}
An addition to the above answer.
If React complains about any of your passed props being undefined, then you will need to destructure those props with default values (common if passing functions, arrays or object literals) e.g.
const CreateProfile = ({
// defined as a default function
onFirstNameChange = f => f,
onHide,
// set default as `false` since it's the passed value
show = false
}) => {...}
just do this on source component
<MyDocument selectedQuestionData = {this.state.selectedQuestionAnswer} />
then do this on destination component
const MyDocument = (props) => (
console.log(props.selectedQuestionData)
);
A variation of finalfreq's answer
You can pass some props individually and all parent props if you really want (not recommended, but sometimes convenient)
<CreateProfile
{...this.props}
show={this.state.showModal}
/>
and then in the CreateProfile component you can just do
const CreateProfile = (props) => {
and destruct props individually
const {onFirstNameChange, onHide, show }=props;

Categories