我有两个组成部分。 MyButton和MyLabel组件。我创建了3个MyButton组件和3个MyLabel组件。每个按钮都有一个不同的增量值。当您单击按钮时,应该更新相应的标签,而不是所有标签。目前所有标签都在更新。
function MyButton(props) {
const onclick = () => {
props.onNumberIncrement(props.toBeIncremented);
};
return <button onClick={onclick}>+{props.toBeIncremented}</button>;
}
const MyLabel = function(props) {
return <label> {props.counter}</label>;
};
function App(props) {
const [counter, mySetCounter] = React.useState(0);
const handleClick = (incrementValue) => {
mySetCounter(counter + incrementValue);
};
return (
<div>
<MyButton
counter={counter}
onNumberIncrement={handleClick}
toBeIncremented={5}
/>
<MyButton
counter={counter}
onNumberIncrement={handleClick}
toBeIncremented={10}
/>
<MyButton
counter={counter}
onNumberIncrement={handleClick}
toBeIncremented={15}
/>
<br />
<MyLabel counter={counter} />
<MyLabel counter={counter} />
<MyLabel counter={counter} />
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
jsfiddle: click here
答案 0 :(得分:1)
创建带有按钮/标签对及其本地状态和步骤的生成器。生成按钮和标签,然后渲染它们:
const useGenerateButtonAndLabel = step => {
const [counter, mySetCounter] = React.useState(0);
const onclick = React.useCallback(
() => mySetCounter(counter + step),
[step, counter]
);
return [
<button onClick={onclick}>+{step}</button>,
<label> {counter}</label>
];
};
function App(props) {
const [button1, label1] = useGenerateButtonAndLabel(5);
const [button2, label2] = useGenerateButtonAndLabel(10);
const [button3, label3] = useGenerateButtonAndLabel(15);
return (
<div>
{button1}
{button2}
{button3}
<br />
{label1}
{label2}
{label3}
</div>
);
}
ReactDOM.render(<App />, document.getElementById('demo'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="demo"></div>
如果您还需要总计,则每个生成的对也可以返回其当前的counter
,并且可以将它们加到父级中。在此示例中,我还使用Array.from()
,映射和缩小来自动创建/渲染项目。
const useGenerateButtonAndLabel = step => {
const [counter, mySetCounter] = React.useState(0);
const onclick = React.useCallback(
() => mySetCounter(counter + step),
[step, counter]
);
// step is used here is a key, but if step is not unique, it will fail. You might want to generate a UUID here
return [
<button key={step} onClick={onclick}>+{step}</button>,
<label key={step}> {counter}</label>,
counter
];
};
const sum = items => items.reduce((r, [,, counter]) => r + counter, 0);
function App(props) {
const items = Array.from({ length: 5 },
(_, i) => useGenerateButtonAndLabel(5 * (i + 1))
);
return (
<div>
{items.map(([button]) => button)}
<br />
{items.map(([, label]) => label)}
<div>Total: {sum(items)}</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('demo'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="demo"></div>
答案 1 :(得分:0)
这是另一个使用单个状态变量的解决方案:
function App(props) {
const [appState, setAppState] = React.useState([
{value: 0, incrementValue: 5},
{value: 0, incrementValue: 10},
{value: 0, incrementValue: 15}
]);
const handleClick = clickedIndex => () => {
setAppState(
appState.map((item, index) => clickedIndex !== index ?
item : ({...item, value: item.value + item.incrementValue})
)
);
};
return (
<div>
{
appState.map(({value, incrementValue}, index) => (
<MyButton
key={index}
counter={value}
onNumberIncrement={handleClick(index)}
toBeIncremented={incrementValue}
/>
));
}
<br />
{
appState.map(
({value}, index) => <MyLabel key={index} counter={value} />
);
}
</div>
);
}