简体   繁体   English

如何在无状态组件中有条件地更新状态?

[英]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>&nbsp;&nbsp;&nbsp;&nbsp;{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>&nbsp;&nbsp;&nbsp;&nbsp;{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}>&nbsp;&nbsp;&nbsp;&nbsp;{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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM