Reactjs 使用React.cloneElement调用父方法

Reactjs 使用React.cloneElement调用父方法,reactjs,react-props,Reactjs,React Props,我试过了,但对我不起作用 /** *路由器.js */ 从“react router dom”导入{BrowserRouter,Route,Switch}; 从“./components/Layout”导入布局; 从“./pages/AddExercise”导入AddExercise; 常数路由器=()=>( ); 导出默认路由器; /** *Layout.js */ 类布局扩展了React.Component{ render(){ const children=React.children.

我试过了,但对我不起作用

/**
*路由器.js
*/
从“react router dom”导入{BrowserRouter,Route,Switch};
从“./components/Layout”导入布局;
从“./pages/AddExercise”导入AddExercise;
常数路由器=()=>(
);
导出默认路由器;
/**
*Layout.js
*/
类布局扩展了React.Component{
render(){
const children=React.children.map(this.props.children,child=>{
返回React.cloneElement(子级{
testFunc:()=>console.log('testfunction'))
});
});
返回(
{儿童}
)
}
}
导出默认布局;
/**
*AddExercise.js
*/
常量AddExercise=({testFunc})=>(
自定义Btn
);

导出默认的AddExercise在您的情况下,问题在于,当您尝试使用
cloneElement
testFunc
传递给子组件时,它作为切换组件的道具传递,在您的情况下,该组件是子组件或布局组件。switch组件对该道具不做任何操作,它不会传递给
AddExercise
组件

处理您的案例的最佳方法是避免使用
cloneElement
,并直接在布局组件中使用路由

/**
*  Router.js
*/

import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Layout from './components/Layout';
import AddExercise from './pages/AddExercise';

const Router = () => (
        <BrowserRouter>
            <Route component={Layout} /> // This is needed so that Layout gets the Router props
        </BrowserRouter>
);

export default Router;

/**
*  Layout.js
*/

class Layout extends React.Component {
    render() {
        return (
          <div>
            <Switch>
              <Route path="/add-exercise" render={(props) => <AddExercise {...props} testFunc: () => console.log('test function')/>} />
            </Switch>
          </div>
        )
    }
}

export default Layout;

/**
*  AddExercise.js
*/

const AddExercise = ({ testFunc }) => (
  <button onClick={testFunc}>Custom Btn</button>
);

export default AddExercise;
/**
*路由器.js
*/
从“react router dom”导入{BrowserRouter,Route,Switch};
从“./components/Layout”导入布局;
从“./pages/AddExercise”导入AddExercise;
常数路由器=()=>(
//这是必要的,以便布局获得路由器道具
);
导出默认路由器;
/**
*Layout.js
*/
类布局扩展了React.Component{
render(){
返回(
console.log('testfunction')/>}/>
)
}
}
导出默认布局;
/**
*AddExercise.js
*/
常量AddExercise=({testFunc})=>(
自定义Btn
);
导出默认的AddExercise;
其他不涉及在布局中写入路由的解决方案将包括创建另一个包含路由的组件,如

  <BrowserRouter>
        <Layout>
            <ChildRoutes />
        </Layout>
    </BrowserRouter>

ChildRoutes.js

export const ChildRoutes = ({ testFunc }) => {
    <Switch>
      <Route path="/add-exercise" render={(props) => <AddExercise {...props}  testFunc={testFunc}/>} />
    </Switch>
}
export const ChildRoutes=({testFunc})=>{
} />
}

我们应该将布局组合到一个组件中,如您共享的文档中所述。您可以尝试创建一个新组件,例如“FullLayout”,它包括Layout和AddExercise组件

/**
FullLayout.js
*/

import React from 'react'
import Layout from './Layout'
import AddExercise from '../pages/AddExercise'

class FullLayout extends React.Component {
    render = () => {
        return (
        <Layout>
            <AddExercise></AddExercise>
            <AddExercise></AddExercise>
        </Layout>
        );        
    }
}

export default FullLayout
/**
FullLayout.js
*/
从“React”导入React
从“./Layout”导入布局
从“../pages/AddExercise”导入AddExercise
类FullLayout扩展React.Component{
渲染=()=>{
返回(
);        
}
}
导出默认完整布局
然后您只需在Router.js中将组件修改为FullLayout

<Route path="/add-exercise" component={FullLayout} />


这应该可以解决问题

谢谢大家!这样做很好:

<Switch>
  <Route path="/add-exercise" render={(props) => <AddExercise {...props}  testFunc={testFunc}/>} />
</Switch>
Layout.js

import { AppProvider } from './AppContext';

class Layout extends React.Component {

    testFunc = () => console.log('test function');

    render() {
        return (
            <AppProvider value={this.testFunc}> // just wrap it with the AppProvider here and send the method
                    {React.cloneElement(this.props.children, this.props)}
            </AppProvider>
        )
    }
}
从“/AppContext”导入{AppProvider};
类布局扩展了React.Component{
testFunc=()=>console.log('testfunction');
render(){
返回(
//只需在此处使用AppProvider包装它并发送方法
{React.cloneElement(this.props.children,this.props)}
)
}
}
AddExercise.js

import {AppConsumer} from './AppContext';

class AddExercise extends React.Component {
    render() {
        return(
            <button onClick={this.props.testFunc}>Custom Btn</button>
        );
    }    
}

export default props => ( // this is the weird part, but works
    <AppConsumer>
      {context => <AddExercise {...props} testFunc={context} />}
    </AppConsumer>
);
从“/AppContext”导入{AppConsumer};
类AddExercise扩展React.Component{
render(){
返回(
自定义Btn
);
}    
}
导出默认道具=>(//这是一个奇怪的部分,但可以工作
{context=>}
);
import {AppConsumer} from './AppContext';

class AddExercise extends React.Component {
    render() {
        return(
            <button onClick={this.props.testFunc}>Custom Btn</button>
        );
    }    
}

export default props => ( // this is the weird part, but works
    <AppConsumer>
      {context => <AddExercise {...props} testFunc={context} />}
    </AppConsumer>
);