You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Sep 3, 2022. It is now read-only.
Copy file name to clipboardExpand all lines: docs/state.html
+15-18
Original file line number
Diff line number
Diff line change
@@ -136,13 +136,18 @@ <h2>Setting State for Complex Types - setState</h2>
136
136
137
137
<p></p>
138
138
<h2>Updating Array State</h2>
139
-
<p>When a component has an array as state, you need to provide a second argument for <code>setState</code>: the index of the array where you want to make the index. For instance, suppose we have a component <code>fruitList</code> that prints out a list of fruits. We notice that the third item in the list is mispelled and want to update it. We can do that as follows:</p>
139
+
<p>When a component has an array as state, you need to use a callback with <code>setState</code>. For instance, suppose we have a component <code>fruitList</code> that prints out a list of fruits. We notice that the third item in the list is mispelled and want to update it. We can do that as follows:</p>
// Use second argument for index in the array you want to update:
145
-
fruitList.setState('Pinapples', 2)</code>
145
+
fruitList.setState(prevState => {
146
+
// Use array splice to replace mispelling:
147
+
prevState.splice(2, 1, 'Pineapples')
148
+
// Don't forget to return the new state:
149
+
return prevState
150
+
}</code>
146
151
</pre>
147
152
<p></p>
148
153
<h2>Updating state for Array of Objects</h2>
@@ -167,25 +172,17 @@ <h2>Updating state for Array of Objects</h2>
167
172
}
168
173
]</code>
169
174
</pre>
170
-
<p>This array is used as the state for a component of users. We want to update Joe's job to Rock Star. You might try to do this:</p>
175
+
<p>This array is used as the state for a component of users. We want to update Joe's job to Rock Star. To update the job, use a callback, make the transform on the state and return it:</p>
171
176
<pre>
172
177
<codeclass="language-javascript">
173
-
// Update job for Joe Bodoni:
174
-
userList.setState({job: 'Rock Star'}, 0)</code>
175
-
</pre>
176
-
<p>Doing the above will actually replace whatever is currently at index 0 with the new object with just the job property. That's because when you use <code>setState</code> on an array with an index value, Composi uses that information to splice the array. As such it is not possible to update an array of objects with <code>setState</code>. To do so you will need to get the state, perform whatever transform you need and then re-assign the state with the new array:</p>
177
-
<pre>
178
-
<codeclass="language-javascript">
179
-
// Proper way to update an object in an array.
180
-
// Get the Joe Bodoni user from state:
181
-
const newState = userList.state[0]
182
-
183
-
// Set job to new value:
184
-
newState.job = 'Rock Star'
185
-
186
-
// Update component's state:
187
-
userList.setState(newState)</code>
178
+
// Update the fist user's job to 'Rock Start':
179
+
userList.setState(prevState => {
180
+
prevState[0].job = 'Rock Star'
181
+
// Return prevState to udpate component:
182
+
return prevState
183
+
})</code>
188
184
</pre>
185
+
<p>Before version 2.4.0 you could update arrays by passing a second argument for the position in the array. That has since been removed in favor of <code>setState</code> with a callback to be inline with how React, Preact and Inferno work.</p>
189
186
<p></p>
190
187
<h2>Complex State Operations</h2>
191
188
<p>As we saw in our last example of arrays, sometimes you will need to get the state, operate on it separately and then set the component's state to that. For example, if you need to use map, filter, sort or reverse on an array, you'll want to get the complete state and perform these operations. Aftwards you can just set the state:</p>
Copy file name to clipboardExpand all lines: tuts/state-n-lifecycle.html
+7-35
Original file line number
Diff line number
Diff line change
@@ -162,12 +162,12 @@ <h2>Using State Correctly</h2>
162
162
<p>Notice how to update the <code>employer</code> property, we passed it in as its own small object literal. When you use <code>setState</code> on state that is an object, it performs a mixin where the new property/value replaces the previous one. In the case where the new property/value don't exist on the state object, they get added.</p>
163
163
164
164
<h2>Updating an Array</h2>
165
-
<p>Updating the state when it is an array of primitive types is easy, just give <code>setState</code>the new value, and a number for the index in the array where you want to update the value. If the index is greater than the current number of items in the state array, the new value will be push onto the array as the last item:</p>
165
+
<p>Updating the state when it is an array is easy, just use a callback <code>setState</code> to update the array:</p>
166
166
<pdata-height="300" data-theme-id="6688" data-slug-hash="POwzeL" data-default-tab="js,result" data-user="rbiggs" data-embed-version="2" data-pen-title="Composi Tuts -State and Lifecycle-5" class="codepen">See the Pen <ahref="https://codepen.io/rbiggs/pen/POwzeL/">Composi Tuts -State and Lifecycle-5</a> by Robert Biggs (<ahref="https://codepen.io/rbiggs">@rbiggs</a>) on <ahref="https://codepen.io">CodePen</a>.</p>
<p>Updating component state when it is an array of simple values is easy, provide new value and array index. But when the component state is an array of objects, it is more complicated. In such a case you need to get the entire object at the index, modify the object, and then set that as the new value at the correct index. Looks like at the problem. Suppose we have an array of persons and we assign it to a component instance called <code>personsList</code>:</p>
170
+
<p>Updating component state when it is an array of objects, it is more not complicate either. Again just use a callback inside <code>setState</code> to update the array's the object values. Suppose we have an array of persons and we assign it to a component instance called <code>personsList</code>:</p>
171
171
172
172
<pre>
173
173
<codeclass="language-javascript">
@@ -186,47 +186,19 @@ <h2>Updating Array of Objects</h2>
186
186
}
187
187
]</code>
188
188
</pre>
189
-
<p>Say we wanted to change Sam Anderson's job to cook. You might think we could do this:</p>
190
-
<pre>
191
-
<codeclass="language-javascript">
192
-
personsList.setState({job: 'cook'}, 2)
193
-
</code>
194
-
</pre>
195
-
<p>The above will indeed update the job at that index. Unfortunately it will also completely replace the entire person object. That is because when you use <code>setState</code> on an array and pass in the index, behind the scenes Composi is splicing the array. Thus the above operation results in this:</p>
196
-
197
-
<pre>
198
-
<codeclass="language-javascript">
199
-
const people = [
200
-
{
201
-
name: 'Joe Bodoni',
202
-
job: 'mechanic'
203
-
},
204
-
{
205
-
name: 'Ellen Vanderbilt',
206
-
job: 'lab technician'
207
-
},
208
-
{
209
-
job: 'developer'
210
-
}
211
-
]</code>
212
-
</pre>
213
-
<p>As you can see, the object at position 2 was replaced with what we passed in. This means that when you have component state that is an array of objects, you need to take a multi-step approach to updating it. There are two ways to do this.</p>
214
-
<ol>
215
-
<li>Get the state, extract the object at the index, perform whatever updates you need to on it, and finally set that modified object back on the state at the same index using <code>setState</code>.</li>
216
-
<li>Pass a callback to <code>setState</code>. In the callback you perform the same operations as above.</li>
217
-
</ol>
189
+
<p></p>
218
190
<h2>Passing a Callback to setState</h2>
219
191
<p>The first approach is of course doable, whoever it can be a bit messy. Using the second approach results in more container result. When passing a callback to <code>setState</code>, the component's state gets passed as the argument of the callback. So, using this approach, let's solve the problem of updating Sam's job:</p>
220
192
221
193
<pre>
222
194
<codeclass="language-javascript">
223
-
peopleList.setState((state) => {
195
+
peopleList.setState(prevState => {
224
196
// Update Sam's job:
225
-
state[2].job = 'cook'
226
-
return state
197
+
prevState[2].job = 'cook'
198
+
return prevState
227
199
})</code>
228
200
</pre>
229
-
<p>When using a callback, you must take care to always return the modified state. Not doing so will result in the state not being updated. Returning the modified state will cause the component state to be updated properly.</p>
201
+
<p>When using a callback, you must take care to always return the modified state. Not doing so will result in the component state not being updated. Returning the modified state will cause the component state to be updated properly.</p>
230
202
231
203
<h2>Updates Use requestAnimationFrame</h2>
232
204
<p>If you have a situation where state can get updated in rapid succession, you might be worried about unnecessary layout thrashing. However, internally Composi performs update with <code>requestAnimationFrame</code>. If even this is too much for you, there are other options to limit how many times state gets set. You could use <ahref='https://www.npmjs.com/package/lodash.debounce' target='__blank'>_.debounce</a> or <ahref='https://www.npmjs.com/package/lodash.throttle' target='__blank'>_.throttle</a> from <ahref='https://lodash.com' target='__blank'>lodash</a>. You could use these on the event causing state to be set, or use them direction on the code setting state.</p>
0 commit comments