Pass State from component to parent - reactjs

If have a Listing page that contains a table component:
class ListingPage extends Component {
static propTypes = {
getTableData: PropTypes.func.isRequired,
};
componentDidMount() {
this.props.getTableData(*I want to Pass in sortlist state here*);
}
render() {
return (
<div>
<Table />
</div>
}
And the Table component maintains a sortlist state:
class Table extends Component {
constructor(props) {
super(props);
this.state = {
sortlist: 'someStringData',
};
render() {
<div>
Table Information etc.
</div>
}
The sortlist is changed in the table component through various functions. How can I pass that sortlist state up to the ListingPage component?

Pass a function along to Table from ListingPage that gets called whenever the sortlist is changed.
ListingPage component:
class ListingPage extends Component {
static propTypes = {
getTableData: PropTypes.func.isRequired,
};
onSortChange(s) {
console.log(s);
}
render() {
return (
<div>
<Table onSortChange={s => this.onSortChange(s)} />
</div>
);
}
}
Table component:
class Table extends Component {
constructor(props) {
super(props);
this.state = {
sortlist: 'someStringData',
};
}
somethingThatTriggersSortListToChange(s) {
this.props.onSortChange(s);
}
render() {
return <div>Table Information etc.</div>;
}
}

Considering above answer, You can also use redux store in this case when you want to pass state from child to parent. Make an action call and store the state in redux store and get the state in parent component. This is another way of playing from child to parent component.
this.props.saveToStore(this.state.sortlist);
In your action file
cost SAVE_TO_STORE = “SAVE_TO_STORE”;
export function saveToStore(sortlist){
return {
type: SAVE_TO_STORE,
sortlist
}
}
Like store state in reducer and get the state in your parent component and return as props i.e., in mapStateToProps(state, props) function using redux connect method.

Related

Create a removable React component without having to re-create remove function

I am looking to create a "delete-able" / removable React component that I can use in multiple different places.
From researching, I can see it is kind of an anti-pattern to create a component that deletes itself and the correct way to do things is for the parent to manipulate the child components rather than child components modifying themselves.
This has led me to write code somewhat along the following lines:
class ParentComponent extends Component {
constructor(props) {
super(props);
this.state = {
data: [ XXX ]
};
}
removeFunc = (index) => {
const test = this.state.data.filter((_,i) => i !== index);
this.setState({data: test});
}
render() {
return (
<div>
{this.state.data.map((el,i) =>
<ChildComponent removeFunc={() => this.removeFunc(i)}/>
)
}
</div>
);
}
}
export default ParentComponent;
class ChildComponent extends Component {
constructor(props) {
super(props);
this.state = {
removeFunc: props.removeFunc
};
}
render() {
return (
<div>
<button onClick={this.state.removeFunc}>Delete Me</button>
</div>
);
}
}
export default ChildComponent;
The issue I have with this is that I have to keep re-writing the removeFunc function in every parent component.
I am VERY new to React, so I'm just curious if there is there a better / different way to do this or is this the correct way?

How to get a componenet instance in React

I want to know if there is possible to get the component instance as I need.
I put my new component as a children in the main state, but is no the same object in both files.
I need to reach children state in my MainComponent. Looking in google for componenet instance doesnt help, maybe I am out of focus and the name of this is different.
Here is my MainComponent:
import React, { Component } from 'react';
import AnotherComponent from './../whatever/AnotherComponent';
class MainComponent extends Component {
constructor(props) {
super(props);
this.state = {
children: [],
};
}
addChild() {
const { children } = this.state;
this.setState({
children: children.push(<AnotherComponent />)
});
}
getChildrenState(component) {
return component.state(); // this doesn't work!
}
render() {
const { children } = this.state;
return (
<div>
{(children.map(i => (<div key={this.getChildrenState(i).id}>{i}</div>))}
</div>
)
}
And This is AnotherComponent
import React, { Component } from 'react';
class AnotherComponent extends Component {
constructor(props) {
super(props);
this.state = {
id: 144,
};
}
render() {
return (
<div>
Here it is my cHild!
</div>
)
}
Putting <AnotherComponent/> to the state doesn't make sense because it's React element object that isn't associated with specific component instance.
Accessing children state in parent component breaks the encapsulation and indicates design problem.
The instance of class component should be retrieved with a ref, and doing so to access instance state is the last resort that may be needed to extend third-party components that don't provide desired functionality.
If AnotherComponent is first-party component, it should be designed accordingly, to not require state to be accessed from the outside:
render() {
return (
<div key={this.state.id}>{this.state.id}</div>
)
}
If the output needs to be more flexible, it can make use of render prop pattern:
render() {
const render = React.Children.only(children);
return (
<div key={this.state.id}>{render(this.state.id)}</div>
)
}
And used like:
<AnotherComponent>{id => <div>{id}</div>}</AnotherComponent>
If you want to access the state of the child component ( here AnotherComponent ) then you can either :
Maintain the state inside the AnotherComponent and pass the value to the parent ( here MainComponent ) on a change listener ( whenever the state changes ), or;
Maintain the state in the parent ( here MainComponent ) and pass the value to the child as prop.
Let me know if you want me to give an example implementation.

Can I set state of imported component in react native?

I want to set state of imported component. Something like
import ProductListing from '../components/ProductListing';
constructor(props){
super(props);
ProductListing = new ProductListing();
ProductListing.state = {someVariable : 'hello'};
}
Send data as props from the component where you want to use and inside the state of that component use it.
Example:
import UserInfo from './userInfo.js'
class UserDetail extends React.Component {
render()
{
return(
<UserInfo myNewState= {//define your state here} />
)
}
}
And inside UserInfo use this:
....
state= {this.props.myNewState}
If your aim is just to update the state of the child component in your case it is ProductListing. So you can do these steps
Create ProductListing as a react class so that you can create a reference for that
class ProductListing extends Component (){
state = {
items: []
}
updateStateItems = (data) => {
this.setState({ items: data })
}
render() {
return(
// your render method code code
)
}}
import ProductListing in your parent class and create a reference for that and in componentDidMount using the reference call functionupdateStateItems with data that you want to set in ProductListing state.
import ProductListing from './ProductListing'
class ParentClass extends Component (){
constructor(props){
super(props)
}
componentDidMount(){
// here use that reference to pass the data that you want to set in state
this.ref.updateStateItems(data)}
render() {
return(
<div>
<ProductListing
// to create a reference of product listing
ref={(ref) => { this.ref = ref }}
/>
</div>
)
}}

Can't pass state value from child to parent component in react native

I have a state inside of child component that I want to use in parent component. This is how my components set:
Child:
export default class Child extends React.PureComponent {
constructor() {
this.state = {
value: "123",
};
}
updateValue(data){
this.props.updateValue(data);
}
componentWillMount(){
this.updateValue(this.state.value);
}
}
Parent:
export default class Parent extends Component {
constructor() {
super(props)
this.state = {
newValue: ""
};
}
updateState (data) {
this.setState(newValue: data);
}
render() {
return(
<Child updateValue={this.updateState.bind(this)}/>
)
}
}
However, it doesn't seem to work and gives me an error. Am I doing something wrong?
Remember that this.setState takes an argument. You have passed a key:value pair that isn't stored in a data structure.
this.setState(newValue: data);
should be
this.setState({newValue: data});

Setting the state with React + TypeScript

I cannot figure out how to set the state of my React component with TypeScript.
I'm making a simple Todo list
I have a component for the entire list: TodoList
I want to seed the list with some items to play around with
I figured I'd send in a simple array as the props to the TodoList component, and then immediately set that as the state so I have something to work off of
import * as React from "react";
import { TodoItem, ITodoItem } from "../TodoItem";
interface ITodoListProps {
items: ITodoItem[];
}
interface ITodoListState {
stateItems: ITodoItem[];
}
export class TodoList extends React.Component<ITodoListProps, Partial<ITodoListState>> {
constructor(props: ITodoListProps) {
super(props);
// Trouble figuring this part out
// I'd like to set the state to the list from the
// props, as a seed.
this.setState({
stateItems: this.state.stateItems
});
}
public render() {
return (
<div>
<ul>
// This should probably be displaying the items from the state, and not the props.
{this.props.items.map((todo, i) => {
return <TodoItem key={i} name={todo.name} />
})}
</ul>
</div>
);
}
}
You need to pass the props.items to the state when constructing the initial state:
export class TodoList extends React.Component<ITodoListProps, Partial<ITodoListState>> {
constructor(props: ITodoListProps) {
super(props);
this.state = {
stateItems: props.items
};
}
...
}
In the constructor when setting the initial state, simply assign the value you want to this.state:
constructor() {
// ...
this.state = { stateItems: ... /* initial value */ }
}
Later in the lifecycle methods or event listeners you can change the state the way you are doing it in the constructor with setState

Resources