简体   繁体   English

React Hooks动态输入

[英]React Hooks dynamic input

I've got a form component , where you can add an input on click of the button, creating a new team, where you can add players for. 我有一个表单组件 ,您可以在单击按钮时添加输入,创建一个新的团队,您可以在其中添加玩家。

The problem is, that if you fill in a value, all inputs will be filled with that value, because it is using the same state. 问题是,如果填写一个值,所有输入都将填充该值,因为它使用的是相同的状态。 My guess is to make a new state value for each new team (something like 'input' + index, which would result in states like input0, input1, input2, etc). 我的猜测是为每个新团队创建一个新的状态值(类似'input'+ index,这将导致input0,input1,input2等状态)。

Though I can't implement this using React Hooks as you have to declare your state at first, and assign a set function to it. 虽然我不能使用React Hooks来实现它,因为你必须首先声明你的状态,并为它分配一个set函数。

Any thought on how I can implement this behaviour? 有关如何实现此行为的任何想法?

Here's just one solution that's pretty straightforward, keeping track of values in an array, just to illustrate that hooks don't make anything more difficult: 这里只是一个非常简单的解决方案,跟踪数组中的值,只是为了说明钩子不会让事情变得更加困难:

function App() {
  let [inputs, setInputs] = useState([""]);

  return (
    <div className="App">
      <button onClick={() => setInputs(inputs.concat(""))}>Add input</button>
      <form>
        {inputs.map((value, i) => (
          <div key={i}>
            <label>Input {i + 1}</label>
            <input
              value={value}
              onChange={e =>
                setInputs(
                  inputs.map((value, j) => {
                    if (i === j) value = e.target.value;
                    return value;
                  })
                )
              }
            />
          </div>
        ))}
      </form>
    </div>
  );
}

codesandbox codesandbox

Structure your state to be like: 构建您的状态如下:

const teams = [
  { name: "Team 1", players: [ /* ... */ ] },
  { name: "Team 2", players: [ /* ... */ ] },
  /* ... */ 
]; 

I encourage you to use useReducer() hook, it fits so well for your case! 我鼓励你使用useReducer()钩子,它非常适合你的情况! It's a bit boilerplaty, but with clean and very understandable code. 它有点像样,但代码干净且易于理解。

function reducer(state, action) {
  switch (action.type) {
    case 'addPlayer':
      // find needed team and push player object there
    case 'addTeam':
      // push new team object into state
    default:
      throw new Error();
  }
}

const [state, dispatch] = useReducer(reducer, teams);

Structure of state may vary, for example you can use keyed object for teams it doesn't matter. 状态结构可能会有所不同,例如,您可以为团队使用键控对象无关紧要。

I would structure the state like this: 我会像这样构建状态:

// initial state
state = { teams: [] }

where each team object has a name and has an array of players: 每个团队对象都有一个名称并且有一系列玩家:

{ name: "team1", players: ["player1", "player2"] }

So the state may end up looking like this: 所以州可能最终看起来像这样:

{ teams: [
  { name: "team1", players: ["player1", "player2"] },
  { name: "team2", players: ["player3", "player4"] },
  { name: "team3", players: ["player5", "player6"] }
  ]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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