You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Redux-Form的React足球投注系统动态表单开发问询

Hey there! Let's walk through how to implement your football betting form with Redux-Form in React, using your existing matches dataset. I'll break this down into actionable steps so you can get up and running quickly.

Step 1: Install Required Dependencies

First, make sure you have all the necessary packages installed. Redux-Form relies on Redux and React-Redux, so run this command in your project directory:

npm install redux-form react-redux redux
# or if you use Yarn:
yarn add redux-form react-redux redux
Step 2: Configure Your Redux Store

You need to add the Redux-Form reducer to your Redux store. Here's how to set that up:

// src/store.js
import { createStore, combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form';

const rootReducer = combineReducers({
  // Add your other reducers here if you have them
  form: formReducer
});

export const store = createStore(rootReducer);

Don't forget to wrap your app with the Redux Provider in your root component:

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { store } from './store';
import BettingForm from './BettingForm';

ReactDOM.render(
  <Provider store={store}>
    <BettingForm />
  </Provider>,
  document.getElementById('root')
);
Step 3: Build the Dynamic Match Form

Now let's create the form component that handles your matches array. We'll use FieldArray from Redux-Form to dynamically render fields for each match, and Field for individual input fields.

// src/BettingForm.js
import React from 'react';
import { reduxForm, Field, FieldArray } from 'redux-form';

// Render a single match's input fields
const renderMatch = ({ fields, index, match }) => (
  <div className="match-row">
    <h4>Match {match.name}</h4>
    <p>{`Team ${match.home_team} vs Team ${match.away_team}`}</p>
    
    {/* Home Result Input */}
    <div>
      <label>Home Team Result:</label>
      <Field
        name={`matches[${index}].home_result`}
        type="number"
        component="input"
        disabled={match.finished} // Disable if match is already finished
      />
    </div>

    {/* Away Result Input */}
    <div>
      <label>Away Team Result:</label>
      <Field
        name={`matches[${index}].away_result`}
        type="number"
        component="input"
        disabled={match.finished} // Disable if match is already finished
      />
    </div>
  </div>
);

// Main form component
const BettingForm = ({ handleSubmit, pristine, reset, submitting }) => {
  // Your existing matches data
  const initialMatches = [
    { 
      name: 1, 
      type: "group", 
      home_team: 1, 
      away_team: 2, 
      home_result: null, 
      away_result: null, 
      date: "2018-06-14T18:00:00+03:00", 
      stadium: 1, 
      channels: [], 
      finished: false 
    },
    { 
      name: 2, 
      type: "group", 
      home_team: 3, 
      away_team: 4, 
      home_result: null, 
      away_result: null, 
      date: "2018-06-14T18:00:00+03:00", 
      stadium: 1, 
      channels: [], 
      finished: false 
    }
  ];

  const onSubmit = (values) => {
    // Handle form submission here - e.g., send to API, update Redux state, etc.
    console.log('Betting Submissions:', values.matches);
    // Example: dispatch an action to save bets
    // dispatch(saveBets(values.matches));
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <h2>Football Betting Form</h2>
      
      {/* Render all matches using FieldArray */}
      <FieldArray
        name="matches"
        component={(props) => (
          <div>
            {initialMatches.map((match, index) => (
              renderMatch({ ...props, index, match })
            ))}
          </div>
        )}
      />

      <div className="form-actions">
        <button type="submit" disabled={pristine || submitting}>
          Submit Bets
        </button>
        <button type="button" disabled={pristine || submitting} onClick={reset}>
          Reset
        </button>
      </div>
    </form>
  );
};

// Connect the form to Redux
export default reduxForm({
  form: 'bettingForm', // Unique identifier for this form
  initialValues: {
    matches: initialMatches // Set initial values from your matches array
  }
})(BettingForm);
Step 4: Add Optional Validation (Bonus)

If you want to add validation (e.g., ensure results are non-negative numbers), you can define a validation function and pass it to the reduxForm HOC:

const validate = (values) => {
  const errors = {};
  if (values.matches) {
    values.matches.forEach((match, index) => {
      if (!match.home_result || match.home_result < 0) {
        errors.matches = errors.matches || [];
        errors.matches[index] = { ...errors.matches[index], home_result: 'Enter a valid non-negative score' };
      }
      if (!match.away_result || match.away_result < 0) {
        errors.matches = errors.matches || [];
        errors.matches[index] = { ...errors.matches[index], away_result: 'Enter a valid non-negative score' };
      }
    });
  }
  return errors;
};

// Update the reduxForm HOC to include validation
export default reduxForm({
  form: 'bettingForm',
  initialValues: { matches: initialMatches },
  validate
})(BettingForm);

Then modify the renderMatch function to display errors:

const renderMatch = ({ fields, index, match, meta: { touched, error } }) => (
  <div className="match-row">
    {/* ... existing code ... */}
    {touched && error && <span className="error">{error}</span>}
  </div>
);
Key Notes to Keep in Mind
  • Disabled Fields: The example disables inputs for finished matches - adjust this logic based on your needs.
  • Dynamic Updates: If your matches array changes after the form loads (e.g., new matches added), you'll need to update the initialValues or use change action from Redux-Form to sync the form state.
  • Styling: Add CSS classes (like .match-row, .error, .form-actions) to style the form to match your app's design.

内容的提问来源于stack exchange,提问作者Fernando Maymone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:37:22