Search code examples
reactjsmaterial-uiprop

call a component from an action- react


I am using functional components in my application, initially it had a component with a lot of code and I divided it into 3 to be able to better organize the code and have reusable components, the first one contains a <MaterialTable>, the second one <dialog> and the third one <form>.

In the component where the table is located import the <dialog>, within the <dialog> component import the <form>, that way the form is inside the dialog box and the dialog box I want to send it to call from the actions of the board.

The problem is that when adding the component in actions I get the following error

Expected an assignment or function call and instead saw an expression

How can I open the component from the actions in the table?

Table

export default function User(){ 

const[user, setUser]= useState({Users:[]});

 useEffect(()=>{
    const getUser=async()=>{
            const response =await axios.get('/api/users');
            setUser(response.data);
            console.log(response.data)
    }
    getUser();
},[]);

return(
<div>
     <MaterialTable
         title="Users"
         columns={[
             { title: 'Code', field: 'code' , type: 'numeric'},
             { title: 'Name', field: 'name' },
             { title: 'Lastname', field: 'lastname' },
             { title: 'Age', field: 'age', type: 'numeric'},
         ]}
         data={user.Users}
actions={[   
    {
      icon: 'event',
      tooltip: 'Agregar cita', 
      onClick:(event, rowData)=>{
        //event.preventDefault();

        <Dialogs/>

     }
    }
  ]} 
         />
 </div>
        );
        }

Dialog

function Dialogs(){
    const [open, setOpen] = useState(false);

    const handleClickOpen = () => {
      setOpen(true);
    };

    const handleClose = () => {
      setOpen(false);
    };
    return(
        <div>
                      <Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
                      <DialogTitle id="form-dialog-title">Subscription></DialogTitle>
                          <DialogContent>
                              <DialogContentText>
                                  Subscription
                              </DialogContentText>
                    <AddSuscription/>
                          </DialogContent>
                      <DialogActions>
                        <Button onClick={handleClose} color="primary">
                          Cancel
                        </Button>
                      </DialogActions>
                    </Dialog>
        </div>
    )
}
export default Dialogs; 

Form

export default function AddSuscription(props){

    const initialState={code:0, email:'', alias:''}

    const[subscription, setSubscription]=useState(initialState);

    const handleChange=(event)=>{
        setSubscription({...subscription,[event.target.name]:event.target.value})
    }

    const handleSubmit=(event)=>{

        event.preventDefault();

        if(!subscription.code || !subscription.email || !subscription.alias) 
            return
                const postSubscription=async()=>{
                    try {
                        axios.post('/api/Subscription/add',subscription);
                        props.history.push('/Subscription'); 
                    }
                    catch (error) {
                        console.log('error', error);
                    }
                }
                postSubscription();
    } 
return(
<div> 
                                  <form onSubmit={handleSubmit} >
                                      <TextField
                                          id="filled-name"
                                          name="code"
                                          label="Code"
                                          value={subscription.code}
                                          onChange={handleChange}
                                          margin="normal"
                                      />
                                      <TextField
                                          id="filled-name"
                                          label="Email"
                                          value={subscription.email}
                                          name="email"
                                          onChange={handleChange}
                                          margin="normal"
                                      />
                                      <TextField
                                          id="filled-multiline-static"
                                          label="Alias"
                                          value={subscription.alias}
                                          name="alias"
                                          onChange={handleChange}
                                          margin="normal"
                                      />
                                      <Button
                                          variant="contained"
                                          color="primary"
                                          type="submit">
                                          Add
                                      </Button>
                                  </form>
<div> 
);
}

Solution

  • onClick:(event, rowData)=>{
        <Dialogs/>
     }
    

    You cannot render from an event handler like this. Where exactly would you expect that component to appear? React just doesn't work that way.

    Instead, keep some state, change that state (which automatically re-renders your component), then conditionally render what you want based on that state.

    Something like this:

    Add state to the main component that needs to render the dialog:

    export default function User() { 
      const [showDialog, setShowDialog] = useState(false)
      //...
    

    Change your event handler to change that state

    onClick:(event, rowData)=>{
      setShowDialog(true)
    }
    

    And in your main render, conditionally render the <Dialogs> component.

    return(

    <div>
        {showDialog && <Dialogs/>}
        <MaterialTable
          {/* ... */}
        />