onClick array.push覆盖前面的元素React



我试图向key: []onclick添加多个值,但它一直覆盖我以前的条目

const handleClick = e => {
console.log('click ', e)
let choice = {
key: e.keyPath[1],
value: [],
}
choice.value.push(e.keyPath[0])
console.log('choice', choice)
let newFilterChoice = {
...filterChoice,
[choice.key]: choice.value,
}
updateFilter(newFilterChoice)
console.log('filter', filterChoice)
}

第一次点击输出看起来像这个CCD_ 2,第二次点击{role: ['new value']}

预期输出应为{role: ['value 1', 'new value']}

在您的示例中,每次调用该函数时都要创建一个新的本地choice变量,因此choice.values将始终以[]开头。

您可能想在那里做的是将choice变量移动到状态,并在每次处理单击时更新它。类似这样的东西:

const App = () => {
const [choiceValues, setChoiceValues] = React.useState([]);

const handleClick = React.useCallback((e) => {
const { value } = e.target.dataset;

setChoiceValues(prevChoiceValues => {
// Append the new value to the old ones creating a new array (no `prevChoiceValues.push`,
// otherwise the reference won't change and React won't be able to track your change:
const nextChoiceValues = [...prevChoiceValues, value];

// Do something else with `nextChoiceValues` here:
// updateFilter(nextChoiceValues);

// Return them to update the state:
return nextChoiceValues;
});
}, []);

const nextValue = choiceValues.length;

return (<React.Fragment>
<button onClick={ handleClick } data-value={ nextValue }>Add value { nextValue }</button>

<pre>{ choiceValues.join(', ') }</pre>
</React.Fragment>);
}
ReactDOM.render(<App />, document.querySelector('#app'));
body,
button {
font-family: monospace;
}
body, p {
margin: 0;
}
#app {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
}
button {
margin: 32px 0;
padding: 8px;
border: 2px solid black;
background: transparent;
cursor: pointer;
border-radius: 2px;
}
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>

您正在用新值替换密钥,而不是附加它。

let newFilterChoice = {
...filterChoice,
[choice.key]: choice.value, // <-- this replaces what used to be there
}

我认为你打算保留之前为密钥设置的值,所以你可能应该这样做:

const oldChoice = filterChoice[e.keyPath[1]];
let choice = {
key: e.keyPath[1],
value: oldChoice ? oldChoice.value : []  // <-- keep existing values
}
choice.value.push(e.keyPath[0])
let newFilterChoice = {
...filterChoice,
[choice.key]: choice.value, 
}

或者你可以避免创建一个新的对象,除非有必要,比如

const oldChoice = filterChoice[e.keyPath[1]];
let choice = oldChoice ? oldChoice : {
key: e.keyPath[1],
value: [] 
}
choice.value.push(e.keyPath[0])
let newFilterChoice = {
...filterChoice,
[choice.key]: choice.value, 
}

假设有几件事,当点击处理程序handleClick被触发时,choicenewFilterChoice等都被重新定义。您可能需要使用this.stateuseState挂钩之类的东西来存储会话。

此外,当您尝试创建newFilterChoice时,实际上会重新创建并添加choice

您可能需要更改此处的逻辑:

let choice = {
key: e.keyPath[1],
value: [],
}

上面的value应该指某个地方存储的选项。一个更好的例子是:

const domContainer = document.querySelector('#root');
class App extends React.Component {
state = {
choices: []
};
handleClick = () => {
const choices = [...this.state.choices];
choices.push(new Date());
this.setState({ choices });
};
render() {
return (
<div className="App">
<pre>{JSON.stringify(this.state.choices, null, 2)}</pre>
<button onClick={this.handleClick}>Click</button>
</div>
);
}
}
ReactDOM.render(<App />, domContainer);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

最新更新