I have found that React does not update a ponent when an element in the array is changed. Instead, a new array must be cloned and put in its place.
For example, I have an array of _suggestedPeople
. When the UI element representing one of these people is clicked, I'd like to register this by calling selectPerson
.
I would expect React to update after doing this:
selectPerson: function(personID, selected) {
var person = _.find(_suggestedPeople, {id: personID});
if (person) {
person.selected = selected;
}
return person;
},
However, I end up doing this instead, which seems unnecessary:
selectPerson: function(personID, selected) {
var index = _.findIndex(_suggestedPeople, {id: personID});
var found = index !== -1;
if (found) {
var people = _.cloneDeep(_suggestedPeople);
people[index].selected = selected;
_suggestedPeople = people;
}
return found;
},
Is this the latter the correct way to update the array data of a React ponent? Or am I missing something?
I have found that React does not update a ponent when an element in the array is changed. Instead, a new array must be cloned and put in its place.
For example, I have an array of _suggestedPeople
. When the UI element representing one of these people is clicked, I'd like to register this by calling selectPerson
.
I would expect React to update after doing this:
selectPerson: function(personID, selected) {
var person = _.find(_suggestedPeople, {id: personID});
if (person) {
person.selected = selected;
}
return person;
},
However, I end up doing this instead, which seems unnecessary:
selectPerson: function(personID, selected) {
var index = _.findIndex(_suggestedPeople, {id: personID});
var found = index !== -1;
if (found) {
var people = _.cloneDeep(_suggestedPeople);
people[index].selected = selected;
_suggestedPeople = people;
}
return found;
},
Is this the latter the correct way to update the array data of a React ponent? Or am I missing something?
Share Improve this question asked May 11, 2015 at 21:51 Matt NorrisMatt Norris 8,85614 gold badges60 silver badges92 bronze badges 4- Perhaps a different approach would fit better in the immutability paradigm. E.g. storing a reference to the selected person object in another property of the ponent instead of mutating the person objects. – Fabrício Matté Commented May 11, 2015 at 21:57
-
Why not just trigger an update when a new selection occurs? React doesn't track properties of objects, so just setting selected of an object wouldn't work. For example, you could call
forceUpdate
. – WiredPrairie Commented May 11, 2015 at 22:12 -
Sorry I am finding it a little hard to follow your code snippets out of context, but I think you should store selected person in the ponents state (or the state of its parent depending on which ponent
selectPerson
is implemented in) and force a re render with a call tothis.setState({_suggestedPeople: people, selectedPerson: person})
. There is a fiddle jsfiddle/map5vf94/11 in the answer of this question which might be what you are trying to do- stackoverflow./questions/30042657/… – Dave Pile Commented May 12, 2015 at 1:00 -
Thank you. I did use
forceUpdate
at first, but felt I shouldn't have to, rather that there was an underlying problem I was circumventing. Maybe that's not the case. For this problem, I need to track multiple selections. Would you advocate a second list?selectedPeople
array instead ofselectedPerson
object? – Matt Norris Commented May 12, 2015 at 18:50
3 Answers
Reset to default 0You don't appear to be using React's built in state management. If you do, a middle ground between your two approaches of updating the state will work. A ponent will re-render when it's state or properties change at all.
Edit: This code is outdated and not good practice. See updated jsfiddle below
Initialise the ponents state by implementing
getInitialState: function () {
var whereverItComesFrom = [
{id: 1, selected: false},
{id: 2, selected: false}
];
return {
suggestedPeople: whereverItComesFrom
}
}
your render method renders from this:
render: function () {
var _this = this;
var peeps = this.state.suggestedPeople.map(function(person, index){
return <label key={index}><input type='checkbox' checked={person.selected} value={person.id} onChange={_this.handlePersonClick}/>{person.id}</label>;
});
return <div>{peeps}</div>;
},
handlePersonClick can be a merge of your methods:
handlePersonClick: function(e) {
var selectedId = e.target.value;
var checked = e.target.checked;
var peeps = this.state.suggestedPeople;
var index = _.findIndex(peeps, {id: selectedId});
peeps[index].selected = checked;
this.setState({suggestedPeople: peeps});
}
Edit: The above was very ill informed early days react for me. I've updated the fiddle link below and it should serve as a good basic example of solving this problem.
Full jsfiddle
I think you are doing it wrong. You may e to react from angular js. Intead of using a function, To manipulate objects, Use useState. Local state with in ponent.
Sample:
const Comp = () => {
const [selectedPerson, setSelectedPerson] = useState({});
function onSelect(personID, selected) {
var person = _.find(_suggestedPeople, { id: personID });
if (person) {
person.selected = selected;
}
setSelectedPerson(person);
}
return (
<div>
{selectedPerson.name}
<select>
<option onSelect={() => onSelect(id, "ssjsjs")}></option>
</select>
</div>
);
};
React setState is a shallow parison, there is no need to use cloneDeep. react can be triggered to re-render only by changing the pointer to the address of _suggestedPeople
. you can try like this:
const App = () => {
const [_suggestedPeople, setSuggestedPeople] = useState([
{
id: '1',
name: 'A',
selected: false,
},
{
id: '2',
name: 'B',
selected: false,
},
])
const handleUserClick = (personID, selected) => {
const person = _.find(_suggestedPeople, { id: personID })
if (person) {
person.selected = selected
}
setSuggestedPeople([..._suggestedPeople])
}
return (
<div>
{_suggestedPeople.map((user) => {
return (
<div
onClick={() => {
// selected or other things
handleUserClick(user.id, true)
}}
className={user.selected ? 'selected' : ''}
>
{user.name}
</div>
)
})}
</div>
)
}
export default App
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745171606a4614959.html
评论列表(0条)