最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Hooks dynamic input - Stack Overflow

programmeradmin3浏览0评论

I've got a form ponent, 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).

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.

Any thought on how I can implement this behaviour?

I've got a form ponent, 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).

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.

Any thought on how I can implement this behaviour?

Share Improve this question asked Mar 18, 2019 at 22:12 JurJur 1852 gold badges3 silver badges10 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 7

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

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! 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"] }
  ]
}
发布评论

评论列表(0)

  1. 暂无评论