enable the go to next step button, tried setting up state and created new onclick method in the radio button

匿名 (未验证) 提交于 2019-12-03 01:29:01

问题:

update 2:

hi,

  • sorry I forgot to mention about the api call in my question earlier
  • I making an api call in redux way.
  • so in my actions/index.js file I am calling my api in getSports method.
  • but the problem is when I try to retrieve the values I am getting an error. A cross-origin error was thrown. React doesn't have access to the actual error object in development. See b.me/react-crossorigin-error for more information.
  • so I debugged the props in the class AsyncValidationForm console.log("AsyncValidationForm this.props---->", this.props);
  • there I dont see the getSports method.
  • can You tell me how to retrieve the values so that I can assign the them to my radio button label.

https://codesandbox.io/s/yv1zpj874x

actions/index.js

import axios from "axios";  export function testData() {   let response = { data: "test" };   return {    }; }  export function getSports() {   return dispatch => {     axios       .get("https://jsonplaceholder.typicode.com/users") //works       .then(response => {        })       .catch(error => {        });   }; } 

AsyncValidationForm.js

import * as actions from "../actions";   class AsyncValidationForm extends React.Component {   constructor(props) {     super(props);     console.log("AsyncValidationForm  this.props---->", this.props);      this.state = {       //pass down VerticalLinearStepper.js state if any       username: this.props.username ? this.props.username : "",       password: this.props.password ? this.props.password : "",       //this determines whether any fields is filled or not from VerticalLinearStepper       pristine:         this.props.username || this.props.password || !this.props.disabledNext           ? false           : true     };   } 

radio button label in AsyncValidationForm.js

  <label>           <Field             name="sex"             component={renderField}             type="radio"             value="male"             checked={!this.props.disabledNext}             onChange={this.passRadioValue}           />{" "}           Male         </label> 
  • I am new to redux form.
  • I am trying to enable the button after I click the radio button.
  • to enable the go to next step button I tried setting up state and created new onclick method in the radio button.
  • but still its throwing an error,
  • not sure how to pass the radio button values to enable the button.
  • Can you tell me how to fix it, so that in future I will fix it myself.
  • Providing my sandbox and relevant code snippet below.

update1: now only this error has been removed https://codesandbox.io/s/4jpkk394x7?moduleview=1

https://codesandbox.io/s/pjj6m1l9pq

AsyncValidationForm.js

const AsyncValidationForm = props => {   console.log("AsyncValidationForm ---->");   const { handleSubmit, pristine, reset, submitting } = props;   // this.state = {    //   disabled: false   // };   // this.setState({ disabled: !this.state.disabled });   const passRadioValue = (e) =>{   }   return (     <form onSubmit={handleSubmit}>       <Field         name="username"         type="text"         component={renderField}         label="Username"       />       <Field         name="password"         type="password"         component={renderField}         label="Password"       />       <label>         <Field name="sex"          component={renderField} type="radio" value="male"           onClick={this.passRadioValue("right")} />{" "}         Male       </label>       <div>         <button type="submit" disabled={submitting}>           Sign Up         </button>         <button type="button" disabled={pristine || submitting} onClick={reset}>           Clear Values         </button>       </div>     </form>   ); }; 

StepTemplate.js

<Button           variant="contained"           color="primary"           onClick={onNext}           className={classes.button}         >           {canGoBack ? "Next" : "go to next step"}         </Button> 

回答1:

https://codesandbox.io/s/6zrw7r66rr

I have forked your codesandbox, and edit 4 files. Pretty sure it satisfies all your requirements stated above

VerticalLinearStepper.js: this is where we store our username, password, disabledNext (radioButton) state and handleChange method for setState. Then, we passed down the state to -> Step1.js -> AsyncValidationForm.js.

class VerticalLinearStepper extends React.Component {   state = {     activeStep: 0,     //we set our state in this parent     disabledNext: true,     username: "",     password: ""   };    steps = {     "Select campaign settings": Step1,     "Create an ad group": Step2,     "Create an ad": Step3   };    //setState for disabledNext   handleChangeDisabledNext = value => {     this.setState({ disabledNext: value });   };   //setState for username, password   handleChange = (name, value) => {     this.setState({ [name]: value });   };    stepsCount = () => Object.values(this.steps).length;    canGoBack = () => this.state.activeStep > 0;   canGoForward = () => this.state.activeStep < this.stepsCount();    isFinished = () => this.state.activeStep === this.stepsCount();    handleBack = () => {     if (this.canGoBack()) {       this.setState(prevState => ({ activeStep: prevState.activeStep - 1 }));     }   };    handleNext = () => {     if (this.canGoForward()) {       this.setState(prevState => ({ activeStep: prevState.activeStep + 1 }));     }   };    handleReset = () => this.setState({ activeStep: 0 });    render() {     const { classes } = this.props;     const { activeStep } = this.state;      return (       <div className={classes.root}>         <Stepper activeStep={activeStep} orientation="vertical">           {Object.entries(this.steps).map(([label, CustomStep]) => (             <Step key={label}>               <StepLabel>{label}</StepLabel>               <StepContent>                 <CustomStep                   canGoBack={this.canGoBack()}                   canGoForward={this.canGoForward()}                   onBack={this.handleBack}                   onNext={this.handleNext}                   classes={classes}                   //we pass down the state and its' setState method                   handleChangeDisabledNext={this.handleChangeDisabledNext}                   disabledNext={this.state.disabledNext}                   handleChange={this.handleChange}                   username={this.state.username}                   password={this.state.password}                 />               </StepContent>             </Step>           ))}         </Stepper>          {this.isFinished() && (           <Paper square elevation={0} className={classes.resetContainer}>             <Typography>All steps completed - you&apos;re finished</Typography>             <Button onClick={this.handleReset} className={classes.button}>               Reset             </Button>           </Paper>         )}       </div>     );   } } 

In AsyncValidationForm.js, we bind onChange method to track the value and call the setState method and this.props.handleChange for setState in VerticalLinearStepper.js

const renderField = ({   input,   label,   type,   //checked is for radio, initialValue is for setting the username, password value   checked,   initialValue,   meta: { asyncValidating, touched, error } }) => {   return (     <div>       <label>{label}</label>       <div className={asyncValidating ? "async-validating" : ""}>         <input           {...input}           value={initialValue} //add value attr           checked={checked} //add checked attr           type={type}           placeholder={label}         />         {touched && error && <span>{error}</span>}       </div>     </div>   ); };  class AsyncValidationForm extends React.Component {   constructor(props) {     super(props);     console.log("AsyncValidationForm ---->");      this.state = {       //pass down VerticalLinearStepper.js state if any       username: this.props.username ? this.props.username : "",       password: this.props.password ? this.props.password : "",       //this determines whether any fields is filled or not from VerticalLinearStepper       pristine:         this.props.username || this.props.password || !this.props.disabledNext           ? false           : true     };   }    passRadioValue = e => {     this.setState({ pristine: false }, () => {       this.props.handleChangeDisabledNext(!e.target.checked);     });   };    handleChange = name => event => {     const value = event.target.value;     this.setState(       {         [name]: value,         pristine: false       },       () => {         this.props.handleChange(name, value); //setState username, password of VerticalLinearStepper.js       }     );   };    resetForm = () => {     this.props.handleChangeDisabledNext(true); //setState disabledNext of VerticalLinearStepper.js     this.setState(       {         username: "",         password: "",         pristine: true       },       () => {         this.props.handleChange("username", "");         this.props.handleChange("password", "");       }     );      this.props.reset();   };    // this.setState({ disabled: !this.state.disabled });    render() {     const { handleSubmit, pristine, reset, submitting } = this.props;      return (       <form onSubmit={handleSubmit}>         <Field           name="username"           type="text"           component={renderField}           label="Username"           initialValue={this.state.username}           onChange={this.handleChange("username")}         />         <Field           name="password"           type="password"           component={renderField}           label="Password"           initialValue={this.state.password}           onChange={this.handleChange("password")}         />          <label>           <Field             name="sex"             component={renderField}             type="radio"             value="male"             checked={!this.props.disabledNext}             onChange={this.passRadioValue}           />{" "}           Male         </label>          <div>           <button type="submit" disabled={submitting}>             Sign Up           </button>           <button             type="button"             disabled={(pristine || submitting) && this.state.pristine} //add state.pristine checking             onClick={this.resetForm}           >             Clear Values           </button>         </div>       </form>     );   } } 

Then, in StepTemplate.js Add disabledNext, checkDisabledNext props. checkDisabledNext to determine whether the Next Button will have conditional checking or not. disabledNext is the disabled value.

const StepTemplate = ({   classes,   canGoBack,   canGoForward,   onBack,   onNext,   text,   children,   //we pass down these 2 values   disabledNext,   checkDisabledNext }) => (   <Fragment>     <Typography>{text}</Typography>      <div className={classes.actionsContainer}>       <div>         {children}          <Button           disabled={!canGoBack}           onClick={onBack}           className={classes.button}         >           Back         </Button>         <Button           variant="contained"           color="primary"           onClick={onNext}           className={classes.button}           //determine whether we should check button disabled or not           disabled={checkDisabledNext ? disabledNext : false}         >           {canGoBack ? "Next" : "go to next step"}         </Button>       </div>     </div>   </Fragment> ); 

This is Step1.js, here we just pass props to StepTemplate and AsyncValidationForm:

const Step = props => (   <StepTemplate     text={`         For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.     `}     //we want to apply checking on Step1.js, so we add checkDisabledNext attribute     checkDisabledNext={true}     // disabledNext={this.props.disabledNext} //no need to do this because will be passed with  {...props} below     {...props}   >     <form>       form for the first step here       <div>test here</div>       <AsyncValidationForm         onSubmit={values => {           console.log(values);           alert(             `Values: username: ${values.username} password: ${values.password}`           );         }}         //these are the props passed down from VerticalLinearStepper.js         handleChangeDisabledNext={props.handleChangeDisabledNext}         disabledNext={props.disabledNext}         handleChange={props.handleChange}         username={props.username}         password={props.password}       />     </form>   </StepTemplate> ); 

Here is the re-render issue fix: https://codesandbox.io/s/vqvxj7ky4y Update VerticalLinearStepper.js, then we dont need Step1.js file anymore, since we write the content of Step1.js in this file:

import React from "react"; import PropTypes from "prop-types"; import { withStyles } from "@material-ui/core/styles"; import Stepper from "@material-ui/core/Stepper"; import Step from "@material-ui/core/Step"; import StepLabel from "@material-ui/core/StepLabel"; import StepContent from "@material-ui/core/StepContent"; import Button from "@material-ui/core/Button"; import Paper from "@material-ui/core/Paper"; import Typography from "@material-ui/core/Typography";  // import Step1 from "./steps/Step1"; import Step2 from "./steps/Step2"; import Step3 from "./steps/Step3";  import StepTemplate from "./steps/StepTemplate"; import AsyncValidationForm from "./forms/AsyncValidationForm";  const styles = theme => ({   root: {     width: "90%"   },   button: {     marginTop: theme.spacing.unit,     marginRight: theme.spacing.unit   },   actionsContainer: {     marginBottom: theme.spacing.unit * 2   },   resetContainer: {     padding: theme.spacing.unit * 3   } });  class VerticalLinearStepper extends React.Component {   state = {     activeStep: 0,     //we set our state in this parent     disabledNext: true,     username: "",     password: ""   };    steps = {     //we pass the content of Step1 here, so we dont have to pass props     "Select campaign settings": props => (       <StepTemplate         text={`         For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.          For each ad campaign that you create, you can control how much you're         willing to spend on clicks and conversions, which networks and         geographical locations you want your ads to show on, and more.     `}         //we want to apply checking on Step1.js, so we add checkDisabledNext attribute         checkDisabledNext={true}         disabledNext={this.state.disabledNext} //use this class' state         {...props}       >         <form>           form for the first step here           <div>test here</div>           <AsyncValidationForm             onSubmit={values => {               console.log(values);               alert(                 `Values: username: ${values.username} password: ${                   values.password                 }`               );             }}             //we use this class setstate , no need to pass down props             handleChangeDisabledNext={this.handleChangeDisabledNext}             disabledNext={this.state.disabledNext}             handleChange={this.handleChange}             username={this.state.username}             password={this.state.password}           />         </form>       </StepTemplate>     ),     "Create an ad group": Step2,     "Create an ad": Step3   };    //setState for disabledNext   handleChangeDisabledNext = value => {     this.setState({ disabledNext: value });   };   //setState for username, password   handleChange = (name, value) => {     this.setState({ [name]: value });   };    stepsCount = () => Object.values(this.steps).length;    canGoBack = () => this.state.activeStep > 0;   canGoForward = () => this.state.activeStep < this.stepsCount();    isFinished = () => this.state.activeStep === this.stepsCount();    handleBack = () => {     if (this.canGoBack()) {       this.setState(prevState => ({ activeStep: prevState.activeStep - 1 }));     }   };    handleNext = () => {     if (this.canGoForward()) {       this.setState(prevState => ({ activeStep: prevState.activeStep + 1 }));     }   };    handleReset = () => this.setState({ activeStep: 0 });    render() {     const { classes } = this.props;     const { activeStep } = this.state;      return (       <div className={classes.root}>         <Stepper activeStep={activeStep} orientation="vertical">           {Object.entries(this.steps).map(([label, CustomStep]) => (             <Step key={label}>               <StepLabel>{label}</StepLabel>               <StepContent>                 <CustomStep                   canGoBack={this.canGoBack()}                   canGoForward={this.canGoForward()}                   onBack={this.handleBack}                   onNext={this.handleNext}                   classes={classes}                 />               </StepContent>             </Step>           ))}         </Stepper>          {this.isFinished() && (           <Paper square elevation={0} className={classes.resetContainer}>             <Typography>All steps completed - you&apos;re finished</Typography>             <Button onClick={this.handleReset} className={classes.button}>               Reset             </Button>           </Paper>         )}       </div>     );   } }  VerticalLinearStepper.propTypes = {   classes: PropTypes.object };  export default withStyles(styles)(VerticalLinearStepper); 

Additional reference: React: Class Component vs Functional Component



回答2:

First thing you will need to do is remove the reference to this from your functional component...

onClick={this.passRadioValue("right")}

TO

onClick={passRadioValue("right")}

Functional components inherit their functional context from the parent function's scope and don't have a this object. this will remove the immediate errors

Here's is a forked version or your codepen I've started for reference...

https://codesandbox.io/s/4jpkk394x7?moduleview=1

And some background on Functional (stateless) vs Class (stateful) components...

https://programmingwithmosh.com/react/react-functional-components/



回答3:

This is a simple code to enable a button on radio button click If you want a more descriptive one please elaborate your question

<html> <script> function enableButton() { 	document.getElementById("button").disabled = true; } </script> <input type="radio" name="gender" value="male" onclick="JaaScript:enableButton()"> Male<br> <button type="button" id="button">Click Me!</button> </html>


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!