Tips for transferring properties from one React component to another React component

I need to figure out how to activate a button in a modal when text is entered into an input field. The form is part of a different class and is utilized within a parent class. How can I pass an onChange method to my form component?

Check out the code for the parent component below:

import React from 'react';
import {
  Button,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle
} from '@material-ui/core';
import CompanyFinancialModalForm from '../CompanyFinancialModalForm/CompanyFinancialModalForm';

interface CompanyFinancialModalState {
  addEnabled: boolean;
}

interface CompanyFinancialModalProps {
  open: boolean;
  onClose: () => void;
}

export class CompanyFinancialModal extends React.Component<
  CompanyFinancialModalProps,
  CompanyFinancialModalState
> {
  constructor(props: CompanyFinancialModalProps) {
    super(props);

    this.state = {
      addEnabled: false
    };
  }

  private enableButton = () => {
    this.setState({ addEnabled: true});
  }

  public render() {
    const { open, onClose } = this.props;
    const { addEnabled } = this.state;
    return (
      <>
        <Dialog
          open={open}
          onClose={onClose}
          className="company-financial-modal"
        >
          <DialogTitle id="company-financial-modal-title">
            {'Company and Financial Data'}
          </DialogTitle>
          <DialogContent>
            <CompanyFinancialModalForm onChange={this.enableButton}/>
          </DialogContent>
          <DialogActions>
            <Button
              id="company-financial-modal-add"
              disabled={!addEnabled}
              onClick={onClose}
              color="primary"
            >
              Add
            </Button>
            <Button
              id="company-financial-modal-cancel"
              onClick={onClose}
              color="secondary"
              autoFocus={true}
            >
              Cancel
            </Button>
          </DialogActions>
        </Dialog>
      </>
    );
  }
}

export default CompanyFinancialModal;

Now let's take a look at the class where the form resides:

import React from 'react';
import axios from 'axios';
import { Form, Field } from 'react-final-form';
import { TextField, Select } from 'final-form-material-ui';
import {
  Paper,
  Grid,
  MenuItem,
} from '@material-ui/core';

export interface IValues {
  company_name: string;
  critical_technology: [];
}
export interface IFormState {
  [key: string]: any;
  values: IValues[];
  submitSuccess: boolean;
}

export default class CompanyFinancialModalForm extends React.Component<{}, IFormState> {
  constructor(props: {}) {
    super(props);
    this.state = {
      company_name: '',
      critical_technology: [],
      values: [],
      submitSuccess: false
    };
  }

  private processFormSubmission = (e: React.FormEvent<HTMLFormElement>): void => {
    e.preventDefault();
    this.setState({ loading: true });
    const formData = {
      company_name: this.state.company_name,
      critical_technology: this.state.critical_technology
    };
    this.setState({
      submitSuccess: true,
      values: [...this.state.values, formData],
      loading: false
    });
    axios.post(`http://localhost:8081/companies`, formData);
  }

  private onChange = (e: React.FormEvent<HTMLInputElement>) => {
    const { name, value } = e.target;
    // other form-related logic
    this.props.onChange({ name, value }, e);
  }

  public render() {
    const { submitSuccess, loading } = this.state;
    const { onChange } = this.props;
    return (
      <div>
        <Form
          onSubmit={this.processFormSubmission}
          // validate={this.validateForm}
          render={({ handleSubmit,/*  reset,  submitting, pristine, values*/ }) => (
          <form onSubmit={handleSubmit} noValidate>
            <Paper style={{ padding: 16 }}>
              <Grid container alignItems="flex-start" spacing={2}>
                <Grid item xs={6}>
                  <Field
                    fullWidth
                    required
                    name="companyName"
                    component={TextField}
                    type="text"
                    label="Company Name"
                    onChange={onChange}
                  />
                </Grid>                
                <Grid item xs={12}>
                  <Field
                    name="critical_technology"
                    label="Critical Technology"
                    component={Select as any}
                  >
                    <MenuItem value="hypersonics">Hypersonics</MenuItem>
                    <MenuItem value="directed_energy">Directed Energy</MenuItem>
                    <MenuItem value="command_control_and_communications">Command, Control and Communications </MenuItem>
                    <MenuItem value="space_offense_and_defense">Space Offense and Defense</MenuItem>
                    <MenuItem value="cybersecurity">Cybersecurity</MenuItem>
                    <MenuItem value="artificial_intelligence_machine_learning">Artificial Intelligence/Machine Learning</MenuItem>
                    <MenuItem value="missile_defense">Missile Defense</MenuItem>
                    <MenuItem value="quantum_science_and_computing">Quantum Science and Computing </MenuItem>
                    <MenuItem value="microelectronics">Microelectronics</MenuItem>
                    <MenuItem value="autonomy">Autonomy</MenuItem>
                  </Field>
                </Grid>
              </Grid>
            </Paper>
          </form>
        )}</Form>
      </div>
    );
  }
}

The goal is to send a prop to

<CompanyFinancialModalForm />
that will trigger the add button once some text is entered into the Textfield.

Answer №1

It would be more helpful in the future to only provide the relevant code, as it can be time-consuming to sift through unnecessary code:

While I may not fully grasp your query, here's my attempt at answering what I believe you are seeking. You can implement an onChange method in the parent component and pass it down as a prop to the form. This way, the form can invoke that function whenever its own onChange event occurs. Below is a simplified example:

class Parent extends Component {
  state = { 
    buttonEnabled: false,
    // formInputValue: '', <-- if needed
  };

  
  onChange({ name, value }, e) {
    // Determine logic to enable or disable the button
    // My assumption of the desired behavior
    if (value) this.setState({ buttonEnabled: true });
    else this.setState({ buttonEnabled: false });
  }

  render() {
    return (
      <Fragment>
        <YourForm onChange={this.onChange} />
        <Button enabled={this.state.buttonEnabled} />
      </Fragment>
    );
  }
}

class YourForm extends Component {
  onChange(e) {
    const { name, value } = e.target;
    // Additional form-related operations
    this.props.onChange({ name, value }, e);
  }
}

Does this align with what you were searching for?

Answer №2

In order to validate and enable a button based on input in React, you can pass a reference to a function from the parent component to a child component. The parent's function can then handle the validation logic for enabling/disabling the button.

Check out a demo on CodeSandbox

Here is a simplified version of the code:

function Child (props) {
  return (
    <input type="text" onChange={props.doIt}/>
  )
}

function App() {
 const [disabled, setDisabled] = useState(true);

 function doIt(e) {
     setDisabled(e.currentTarget.value.length === 0);
 }
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <Child doIt={doIt} />
      <button disabled={disabled}>Add</button>
    </div>
  );
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When attempting to check and uncheck checkboxes with a specific class, the process fails after the first uncheck

I have a set of checkboxes and one is designated as "all." When this box is clicked, I want to automatically select all the other checkboxes in the same group. If the "all" box is clicked again, I would like to deselect all the other checkboxes. Currently ...

Store images securely in a private S3 bucket for access with Next.js

I am looking to access images from a private bucket instead of a public one. The code snippet below shows how I currently try to access the images, but I believe there must be a way to do so without making the entire bucket public. In my API file, I use AC ...

Having trouble accessing TreeView Icons and IconButton in my testing environment

Trying to verify a component with an endAdornment IconButton and TreeView. Testing events can be challenging as the IconButton and ExpandIcon/CollapseIcon lack suitable options for dispatching test events. Here is the TextField component in question: < ...

Is there a way to enlarge images when hovered using canvas?

I came across a fascinating example at the following link: , where the images expand when hovered over. I am aware that this can be achieved using jquery, but I have concerns about its speed and reliability. I would like to experiment with d3.js, although ...

Shifting an element to the right before revealing or concealing it with Jquery Show/Hide

$(document).ready(function(){ var speed = 700; var pause = 3500; function removeFirstElement(){ $('ul#newsfeed li:first').hide('slide', {direction: "up"}, speed, function() {addLastElement(thi ...

There seems to be an issue with the hydration process in NextJS when using styled-components with a component

Currently, I am in the process of developing a component library for a brand new nextJS application. This nextJS application utilizes the "app router" feature. Everything functions perfectly when I directly integrate styled-components into the nextJS code ...

The ant layout slider collapsible feature is unable to be utilized in conjunction with SSR in NextJs

Incorporating antd into my NextJs app, I have implemented a Layout component at the top level of my application. /* _app.tsx */ function MyApp({ Component, pageProps }: AppProps) { return ( <Provider store={store}> <SideMenuLayout> ...

Ways to prevent the component from rendering until the ajax call has finished in reactjs

I am working on a project with a parent component and child component. The parent component contains a form where users input their name and phone number, and upon pressing submit, I want these values to be passed as props to the child component. The chi ...

Mastering regular expressions in TypeScript

My goal is to perform linting on staged files that are either .ts or .tsx and located within the src folder. I am aware that for selecting all js files one can use "*.js": [--list of commands--] inside the lint staged property. I'm curious to learn m ...

Issue with displaying nested React Elements from Component

I am currently facing an issue with my Collection component, which is utilizing a sub-component called RenderCollectionPieces to display UI elements. Strangely, I am able to see the data for image.name in the console but for some reason, the UI elements ar ...

MUI: Autocomplete received an invalid value. None of the options correspond to the value of `0`

Currently, I am utilizing the MUI autocomplete feature in conjunction with react-hook-form. I have meticulously followed the guidance provided in this insightful response. ControlledAutoComplete.jsx import { Autocomplete, TextField } from "@mui/mater ...

"Encountering issues with react-swipable-views when attempting to use it

I'm currently working on implementing react-swipable-views into my React application, but I encountered a specific error message: Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite component ...

Issue: $controller:ctrlreg The controller named 'HeaderCntrl' has not been properly registered

I am encountering an error while working on my AngularJS program. I have defined the controller in a separate file but it keeps saying that the controller is not registered. Can someone please help me understand why this issue is happening? <html n ...

What steps can you take to resolve the "TypeError: Cannot read property 'id' of undefined" issue?

I have been developing an app that involves using databases to add items for users based on their user ID, which is their username. However, whenever I attempt to add an item, I encounter an error that I can't seem to troubleshoot. The error message r ...

Understanding the mechanics of utilizing node modules and requiring them within an Express 4 router

After initiating a node project using an express 4 generator, I have set up the following routing code in the /routes/index.js file: // ./routes/index.js var express = require('express'); var router = express.Router(); router.get('/' ...

Ways to emphasize search outcomes in Flask/HTML?

I am currently working on creating a search box using HTML and the Flask framework in Python. Below is the layout I am working with: Layout My goal is to input text into the search box and have it highlighted within the text area on the same HTML page. F ...

A chosen class containing a nested class that utilizes the makeStyles function

Can someone explain how to target the 'element' when the root is selected? Here is the makeStyles code snippet: const useStyles = makeStyles(theme => ({ root:{ '&.selected': { } }, element: { } }) And h ...

Is there a way to implement full-page scrolling in Vue?

Looking for a Vue equivalent of the fullpage.js library. Need a component that allows scrolling through elements similar to fullpage.js. ...

Error encountered in Angular $injector:unpr while attempting to initialize uibModal

I followed the ui-bootstrap tutorial to create my code. On my homepage, there is a button that triggers a modal window to open using ng-click. However, when I check the dev tools, I encounter the following error: Error: [$injector:unpr] Unknown provider: ...

Error Encountered: AngularJS Form Email - SyntaxError: An unexpected token '<' was found in the code

My attempt to send an email from my AngularJS website involves the following setup: Contact.index.html: <form name="userForm" class="well form-search"> <input type="text" ng-model="name" class="input-medium search-query" placeholder="Name" ...