首页 > 解决方案 > React - 如何从子功能组件执行功能

问题描述

我需要你的帮助,我需要在 React 中重用一个组件。现在我有一个设置页面,人们可以在其中配置与其他应用程序的一些连接。不同的应用程序设置看起来有些相同,但并不完全一样。当然我可以用道具来解决这个问题,但buttonClick代码也不同,我不知道怎么做。以下是 1 个设置的示例:

const DarkSky = ({auth}) => {
    const [config, setConfig] = useState(getLocalStorage('darksky') || {api_key: '', success: false});

    const saveConfig = async () => {
        const data = await makeAPICall('/api/darksky/current', 'GET', null, await auth.getAccessToken())
        setConfig({api_key: config.api_key, success: true})
    }

    useEffect(() => {
        setLocalStorage('darksky', config)
    }, [config])


    const configHandler = (event) => setConfig({...config, 'api_key': event.target.value});

    const buttonClickHandler = (event) => saveConfig()

    let formItems = [{
        name: 'apikey',
        type: 'input',
        label: 'API key',
        value: config.api_key,
        changehandler: configHandler
    }] 

    return <div><h2>DarkSky connection</h2>

        <DefaultFormRow data={formItems} buttons={[{id: 'saveapikey', click: buttonClickHandler, buttonclass: (config.success ? 'success' : 'danger'), disabled: false, text: 'Sla API key op'}]} />
        <p>Config correct: {config.success === true ? 'Ja' : 'Nee'} </p>
    </div>  

}

在这个(工作)示例中,有受控输入(formItems)使用以下代码更新配置状态 const configHandler = (event) => setConfig({...config, 'api_key': event.target.value});:我可以通过执行以下操作使其可重用: const configHandler = (event) => setConfig({...config, [event.target.name]: event.target.value});

然后有一个 buttonClick 处理程序,在人们单击保存按钮后触发。在这种情况下它会触发saveConfig(),但在其他情况下,它需要做其他事情。如果我从父组件(设置页面)传递它,这个函数将从父组件执行,我无法访问这个子组件的状态。

你们应该怎么做呢?我不认为我可以在子类中执行函数吗?而且我不想在父类中添加所有这些不同的状态,因为我喜欢这种干净的外观(状态在它自己的组件中)。

不知道我有没有说清楚,如果你们问,我会添加更多细节。

编辑:此时我有这个:

const APIManagement = ({auth}) => {
    return <div>
        <SolarEdge />
        <Tado />
        <DarkSky />
        <Enelogic />

    </div> 
}

这里的不同组件看起来很像,所以如果我能有这样的东西会很好:

const APIManagement = ({auth}) => {

    const saveFunction1 = () => {how to save tado settings here}
    const saveFunction2 = () => {how to save enelogic settings here}
    const saveFunction3 = () => {how to save darksky settings here}
    const saveFunction4 = () => {how to save solaredge settings here}

    return <div>
        <APISetting title='Tado' saveFunction={saveFunction1}/>
        <APISetting title='Enelogic' saveFunction={saveFunction2}/>
        <APISetting title='DarkSky' saveFunction={saveFunction3}/>
        <APISetting title='SolarEdge' saveFunction={saveFunction4}/>

    </div>

}

EDIT2:通过保存功能将设置从浏览器添加到 localStorage 来保持设置:

    useEffect(() => {
        setLocalStorage('darksky', config)
    }, [config])

标签: reactjs

解决方案


在子功能组件中,您可以传递由功能组成的道具对象。在该函数中,将您的子功能组件状态传递到那里并在父组件中设置状态,当它呈现时,它将新状态传递回功能组件。

父类:-

parentFunction = () => {
   //set your state here
}
render() {
   return(
     <DarkSky auth={xyz} parentFunction={this.parentFunction} {...this.state}/>
   )
}

子功能组件:-

const DarkSky = ({auth, parentFunction, state}) => {
}

正如您一直在使用反应钩子一样,它具有隔离状态的功能。所以你可以做的是制作一个可重用的组件(自定义钩子): -

//put this is another js file
export function useConfig(key, defaultConfig) {
  const [config, setConfig] = useState(getLocalStorage(key) || 
  defaultConfig);

  useEffect(() => {
        setLocalStorage(key, config)
    }, [config])
  return config;
}

import { useConfig } from '/js/file/path'
const APISetting = ({title, saveFunction}) => {
    let config = useConfig(title, {api_key: '', success: false})
    const saveConfig = async () => {
        const data = await makeAPICall(`/api/${title}/current`, 'GET', null, await auth.getAccessToken())
//        setConfig({api_key: config.api_key, success: true})
          const newConfig = useConfig({api_key: config.api_key, success: true})
          saveFunction(newConfig);
    } 

    const configHandler = (event) => { config = useConfig({...config, 'api_key': event.target.value}) };

    const buttonClickHandler = (event) => saveConfig()

    let formItems = [{
        name: 'apikey',
        type: 'input',
        label: 'API key',
        value: config.api_key,
        changehandler: configHandler
    }] 

    return <div><h2>{title} connection</h2>

        <DefaultFormRow data={formItems} buttons={[{id: 'saveapikey', click: buttonClickHandler, buttonclass: (config.success ? 'success' : 'danger'), disabled: false, text: 'Sla API key op'}]} />
        <p>Config correct: {config.success === true ? 'Ja' : 'Nee'} </p>
    </div>  

}

In your parent component you will get like this :-

const APIManagement = ({auth}) => {

    const saveFunction1 = (config) => {console.log('the config is', config)}
    const saveFunction2 = () => {how to save enelogic settings here}
    const saveFunction3 = () => {how to save darksky settings here}
    const saveFunction4 = () => {how to save solaredge settings here}

    return <div>
        <APISetting title='Tado' saveFunction={saveFunction1}/>
        <APISetting title='Enelogic' saveFunction={saveFunction2}/>
        <APISetting title='DarkSky' saveFunction={saveFunction3}/>
        <APISetting title='SolarEdge' saveFunction={saveFunction4}/>

    </div>

}

推荐阅读