将React值从子级传递到父级

时间:2020-07-19 03:45:43

标签: reactjs rxjs material-ui

我正在努力制定出可能非常简单的方法。我的父组件是一个搜索窗口小部件,它需要使用在单独的抽屉组件中定义的过滤器。当前,用户可以键入搜索查询,该查询调用一个API,并且需要基于抽屉组件中的选择器来过滤结果。但是,我无法链接父母和孩子来实现这一目标!

父组件(其中包括''组件):

function SuburbSearch(props: Props) {
    const classes = useStyles();
    const [value, setValue] = React.useState<App.Suburb | null>(null);
    const [inputValue, setInputValue] = React.useState('');
    ...
    
    return (
    <Autocomplete
      id="search"
      getOptionLabel={(option) => (typeof option === 'string' ? option : option.name + ' ' + option.state)}
      filterOptions={(x) => x}
      options={options}
      ...
      ...
      renderInput={(params) => (
        <TextField
          {...params}
          label="Search for a suburb"
          ...,
            startAdornment: (
              <InputAdornment position="start">
                <Filters></Filters>
              </InputAdornment>
            ),
            endAdornment: (
              <React.Fragment>
                {loading ? <CircularProgress color="inherit" size={20} /> : null}
                {params.InputProps.endAdornment}
              </React.Fragment>
            ),
          }}
          fullWidth
        />
      )}

子组件(这是“过滤器”):

export default function Filters() {
  const classes = useStyles();
  const [state, setState] = useState(false);
  const [dollar, setDollars] = useState<number[]>([0, 20000000]);
  const [type, setType] = React.useState<string | null>('all');
  
  ...
  const list = (anchor: Anchor) => (
    <div className={classes.root} 
      role="presentation" /*onClick={toggleDrawer(false)} onKeyDown={toggleDrawer(false)}/*/>
      <Grid className={classes.main} container spacing={2}>
        <Grid className={classes.row} item xs={1} md={2} />
        <Grid className={classes.row} item xs={10} md={8}>
          <Typography className={classes.header} align='center' gutterBottom>
            Property Type
          </Typography>
          <ToggleButtonGroup value={type} onChange={handleTypeChange} exclusive>
            <ToggleButton value="all" >All</ToggleButton>
            <ToggleButton value="some" >Some</ToggleButton>
          </ToggleButtonGroup>
        </Grid>
        ...
      </Grid>
   </div>
}

2 个答案:

答案 0 :(得分:1)

您可以简单地通过将函数作为道具来实现,就像这样:

父组件

@extends('layouts.master')
@section('content')


{{--//Blade view--------------------------------------------------------------------------------------------------------}}

<div class="">
    <div class="card">
        <div class="card-body">
            <div class="row">
                <div class="col-lg-12 borrower_id">
                    <div class="pull-left">
                        <h2>Pending Loans</h2>
                    </div>
                </div>
                    <div class="col-xs-3 col-sm-3 col-md-3 "  >
                        <h6>Branch</h6>
                        <input class="form-control" type="text" placeholder="Branch Name" aria-label="Search" id="branch_selector" name="branch_selector" value="" >
                    </div>
                    <div class="col-xs-3 col-sm-3 col-md-3" >
                        <h6>Center</h6>
                        <input class="form-control" type="text" placeholder="Center Name" aria-label="Search" id="center_selector" name="center_selector" value="" >
                    </div>
                    <div class="col-xs-3 col-sm-3 col-md-3" >
                        <h6>Group</h6>
                        <input class="form-control" type="text" placeholder="Group Number" aria-label="Search" id="group_selector" name="group_selector" value="">
                    </div>
                    <div class="col-xs-3 col-sm-3 col-md-3" >
                         <h6>Search</h6>
                        <button type="submit"><i class="fa fa-search"></i></button>
                    </div>

            </div>
        </div>
    </div>
</div>

{{-- @if ($message = Session::get('success'))
<div class="alert alert-success">
    <p>{{ $message }}</p>
</div>
@endif --}}

<table class="table table-bordered" id="loan_table">
    <tr>
        <th>No</th>
        <th>Borrower No</th>
        <th>Loan Stage</th>
        <th>Loan Amount</th>

        <th>Release Date</th>


        <th width="200px">Action</th>
    </tr>
    @foreach ($loans as $loan)



    <tr>
        <td>{{ ++$i }}</td>
        <td>{{ $loan->borrower_no }}</td>
        <td>{{ $loan->loan_stage }}</td>
        <td>{{ $loan->loan_amount }}</td>

        <td>{{ $loan->release_date }}</td>

        <td width="100px">

            <form action="{{ route('approving.destroy',$loan->borrower_no) }}" method="POST">

                <a class="btn btn-info btn-sm" href="{{ route('approving.show',$loan->borrower_no) }}">Details of Borrower</a>
                {{--<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" >Show</button>--}}
                <a class="btn btn-success btn-sm" href="/approving/test/{{$loan->borrower_no}}">Approve</a>

                @csrf
                @method('DELETE')

                <button type="submit" class="btn btn-danger btn-sm">Reject</button>
            </form>
        </td>

    </tr>

    @endforeach
</table>

{!! $loans->links() !!}
-------------------Ajax part---------------------

@section('scripts')
<script type="text/javascript">
        $(document).ready(function () {
        $(group_selector).click(function () {
            var group = $(this).val();
            console.log(group);
            var tmp = null;
            $.ajax({
                type: 'GET',
                url: '{{ ('/gseclector') }}',
                data: {'id':group},
                dataType: 'JSON',
                success: function (data) {
                    console.log(data);

                        
                    data.forEach(function(item){

                   $('#loan_table').append('$loans'+item);
                

                   })
                 });
                }
            });

        });
        });


</script>

子组件

childCallback(value) {
    // value passed from child
}

return {
    <ChildComponent passToParent={this.childCallback}/>
}

答案 1 :(得分:1)

在这里,我正在为您提供Pure React中的一些基本状态管理技术,因为到目前为止,我是通过在注释部分与您讨论而了解的。

模式1,直达

假设您有一个组件comp1,它有一些道具,其中包括需要直接来自其子组件的数据的方法,比如说Comp2

const Comp1 = ({ onActionOrChild }) => {
  return (
    <>
      <Comp2 onAction={onActionOrChild} />
    </>
  )
}

const Comp2 = ({ onAction }) => {
  return (
    <form onSubmit={onAction}>
      ...
    </form>
  )
}

简而言之,这里有一个组件,该组件需要来自其后代之一的某些数据,例如一些表单数据,因此我们将其传递给了这些子对象。但是这里的问题 道具钻探 Comp1需要获得一个它从未使用过的道具。

模式2,使用Context API解决道具钻探

现在,反应 Context API 是稳定的,它对于实现以前需要其他状态管理库的功能非常强大。

版本16.3引入了新的上下文API,该API效率更高, 支持静态类型检查和深度更新。 -Docs

如果我们使用上下文API,则可以从组件中提取这些方法并将其放入一个新文件中,这将创建上下文提供程序,以便应用程序中的不同组件可以彼此通信,而无需传递道具到从未使用过的中间组件到组件之间的几级下降。

Context.js

export const AppContext = createContext();

export AppContextProvider = ({children}) => {

  const onAction = () => {}
  return (
    <AppContextProvider.Provider
      value={{onAction}}
    >
    {children}
    </AppContextProvider.Provider>
  )
  
}

现在,如果我们需要在应用程序的任何部分中使用一种方法,我们只需连接 context API

import { AppContext } from "./Context.js"

const comp3 = ({}) => {
  const { onAction } = useContext(AppContext);
  
  return (
    <form onSubmit={onAction}>
    ...
    </form>
  )
}