Let's say I am mapping my store state to props like so:
const mapStateToProps = state => {
return {
somelist: state.somelist
};
};
And I need to create variables in my render like:
render() {
const { somelist } = this.props;
const somenestedlist = somelist.list;
}
However, in my render method I am also calling another method that needs those same variables. So I can either:
(1) Pass it from the render method like:
render() {
const { somelist } = this.props;
const somenestedlist = somelist.list;
<div onClick={()=>this.someothermethod(somenestedlist)}
}
(2) Redeclare them in the someothermethod()
which is not DRY.
(3) Create a function that returns the needed value and call it wherever it's needed as in:
getList() {
const { somelist } = this.props;
const somenestedlist = somelist.list;
return somenestedlist;
}
OR is there a better way than any of these examples?
You can convert somenestedlist in mapStateToProps:
const mapStateToProps = state => {
return {
somelist: state.somelist,
somenestedlist: state.somelist.list
};
};
In everywhere, you can use this.props.somenestedlist
If you don't need to alter the list, then this.props.someList
is accessible from within any of the class' methods.
However, if you want to add/remove items from this list from within the component without changing someList
, then the simplest solution is to declare a nestedList
variable from the someList
source in the class constructor (the example below, where state = {...}
, is syntactic sugar for the same thing), and then utilize React state to alter this new list.
Now, you can either discard the new list or call a Redux action creator to save and update the props list (consequently, you can also reset both lists as long as the initial list source stays constant).
Working example: https://codesandbox.io/s/6w5r5o32qk
import React, { Component, Fragment } from "react";
import { connect } from "react-redux";
import { resetList, saveList } from "./listActions";
const newData = [
{
_id: "5b9c3b351e5f7d9b827df4ce",
index: 0,
guid: "048e6f79-c33c-42fc-83e3-05f5b467240d",
isActive: false,
balance: "$1,663.79",
picture: "http://placehold.it/32x32",
age: 23,
name: "Tonya Drake"
},
{
_id: "5b9c3b350e7b14d4c94043f2",
index: 1,
guid: "1e3daeeb-36fd-4e52-a30e-5dbaedec8438",
isActive: true,
balance: "$2,263.69",
picture: "http://placehold.it/32x32",
age: 40,
name: "Patricia Phelps"
}
];
class Example extends Component {
state = {
addButtonClicked: false,
saveButtonClicked: false,
nestedList: this.props.someList
};
componentDidUpdate = prevProps => {
if (prevProps.someList !== this.props.someList) {
this.setState({
nestedList: this.props.someList
});
}
};
addData = () => {
this.setState(prevState => ({
addButtonClicked: true,
nestedList: [...this.state.nestedList, newData]
}));
};
resetData = () => {
this.setState(prevState => {
this.props.resetList();
return {
addButtonClicked: false,
saveButtonClicked: false,
nestedList: this.props.someList
};
});
};
saveNewList = () =>
this.setState(prevState => {
this.props.saveList(this.state.nestedList);
return { saveButtonClicked: true };
});
render = () => (
<div style={{ textAlign: "center" }}>
<h1>Utilizing React State</h1>
<button
className="uk-button uk-button-primary uk-button-large"
type="button"
onClick={this.addData}
disabled={this.state.addButtonClicked || this.state.saveButtonClicked}
style={{ marginRight: 20 }}
>
Add Data
</button>
<button
type="button"
className="uk-button uk-button-danger uk-button-large"
onClick={this.resetData}
disabled={!this.state.addButtonClicked && !this.state.saveButtonClicked}
style={{ marginRight: 20 }}
>
Reset List
</button>
<button
type="button"
className="uk-button uk-button-secondary uk-button-large"
onClick={this.saveNewList}
disabled={
(this.state.addButtonClicked && this.state.saveButtonClicked) ||
(!this.state.addButtonClicked && !this.state.saveButtonClicked)
}
>
Save List
</button>
<pre style={{ height: 600, overflowY: "auto", textAlign: "left" }}>
State List
<code>{JSON.stringify(this.state.nestedList, null, "\t")}</code>
<br />
<br />
Props List
<code>{JSON.stringify(this.props.someList, null, "\t")}</code>
</pre>
</div>
);
}
export default connect(
state => ({ someList: state.list }),
{ resetList, saveList }
)(Example);
If you don't want to redeclare variables in every function you use, then... I think your only option is to use the value directly from the props...
Then, do this:
yourMethod(){
//Do somethign with data directly, no need to declare a const again
this.anotherMethod(this.props.somelist.list);
}
instead of:
const { somelist } = this.props;
const somenestedlist = somelist.list;
I mean, the values ARE already available to all methods, just use them... const { somelist } = this.props;
is only used as a helper to not write this.props.somelist
all over the method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With