[英]How to update state conditionally in Stateless Component?
I have two components. 我有两个组成部分。 MyButton and MyLabel component.
MyButton和MyLabel组件。 I created 3 MyButton Compoents and 3 MyLabel Components.
我创建了3个MyButton组件和3个MyLabel组件。 Each button has a different increment value.
每个按钮都有一个不同的增量值。 When you click on a button , the respective label should be updated not all the labels.
当您单击按钮时,应该更新相应的标签,而不是所有标签。 At present all the labels are updating.
目前,所有标签都在更新。
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 jsfiddle: 单击此处
Create a generator of button/label pairs with their local state and step. 创建按钮/标签对的生成器及其本地状态和步骤。 Generate the buttons and labels, and render them:
生成按钮和标签,并进行渲染:
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>
If you also need a total, each generated pair can also return it's current counter
, and you can sum them in the parent. 如果还需要总计,则每个生成的对也可以返回其当前
counter
,并且可以将它们加到父级中。 In this example, I also automate the items creation/rendering with Array.from()
, map, and reduce. 在此示例中,我还使用
Array.from()
,map和reduce来自动创建/渲染项目。
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>
Here is another solution using a single state variable : 这是使用单个状态变量的另一种解决方案:
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>
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.