繁体   English   中英

使用 function Javascript/React 中的字符串动态调用函数/变量

[英]Dynamically call a function/variable using a string inside a function Javascript/React

我试图找到一种方法来动态调用给定字符串的 function 或引用给定字符串的变量。 例如:

import React, {useState} from 'react'

const array = [
  {
    text: 'count1',
    setFunctionName: 'setCount1',
    otherdata: {}
  },
  {
    text: 'count2',
    setFunctionName: 'setCount2',
    otherdata: {}
  }
]

const myFunction = () => {
  const  [count1, setCount1] = useState(0)
  const  [count2, setCount2] = useState(0)

  return(
     <div>
       {array.map((item) => {
          // I want to use item.text to reference the correct count variable
          // I want to use item.setFunctionName to change the correct count 
        })}
     </div>
  )
}

具体用例是我想创建一个可重用的侧边栏菜单,其中链接的数据存储在单独文件中的对象数组中。 一些菜单项将具有可折叠的子菜单,我需要使用 state 管理子菜单的打开和关闭。 例子:

import { Button, Collapse } from 'react-bootstrap'

function Example() {
      const [open, setOpen] = useState(false);
    
      return (
        <>
          <Button
            onClick={() => setOpen(!open)} //**I want to dynamically set this when mapping over the array**
          >
            click
          </Button>
          <Collapse in={open}> //**I want to dynamically set this when mapping over the array**
            <div id="example-collapse-text">
              This is example collapsed text
            </div>
          </Collapse>
        </>
      );
    }

实现这一点的最佳方法可能是使用减速器。

https://reactjs.org/docs/hooks-reference.html#usereducer

可能是这样的?

const initialState = {count1: 0, count2: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'setCount1':
      return {
        ...state,
        count1: action.value
      };
    case 'setCount2':
      return {
        ...state,
        count2: action.value
      };
    default:
      throw new Error();
  }
}

const array = [
  {
    text: 'count1',
    setFunctionName: 'setCount1',
    otherdata: {}
  },
  {
    text: 'count2',
    setFunctionName: 'setCount2',
    otherdata: {}
  }
]

const myFunction = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return(
     <div>
       {array.map((item) => {
          return <a onClick={ () => dispatch({ type: item.setFunctionName, value:3 }) }>{state[item.text]} <a/>
        })}
     </div>
  )
}

如果您不想一直移动到useReducer ,那么将 object 保存到useState也可以,而不是对每个单独的字段进行单独的useState调用:

  import React, {useState} from 'react'

  const array = [
    {
      text: 'count1',
      otherdata: {}
    },
    {
      text: 'count2',
      otherdata: {}
    }
  ]

  const myFunction = () => {
    // This could even be initialised based on the items in `array`
    const  [count, setCount] = useState({
      count1: 0,
      count2: 0,
    });

    return(
       <div>
         {array.map((item, index) => {
            // I want to use item.text to reference the correct count variable
            const countValue = count[item.text];
            
            const updateCount = () => {
              setCount((prevCount) => {
                return {
                  ...prevCount,
                  [item.text]: prevCount[item.text] + 1,
                };
              });
            };
            
            return (
              <button key={index}
                onClick={updateCount}
              >{item.text}: { countValue }</button>
            );
          })}
       </div>
    )
  }

我可能错了,但听起来如果你使用 react-bootstrap,你可能想要使用手风琴组件,因为它的外观和行为可能更接近你正在寻找的东西。 但无论哪种方式,在展开时填充显示的内容都将被类似处理。 如果您的展开内容保存在 state object 中,它应该会随着 state 的变化而自动更新。 您可以在给定数组上 map 并渲染 JSX

<Collapse in={open}> //**I want to dynamically set this when mapping over the array**
    array.map(element => {
        return(
            <div>
                {element.text
                 element.setFunctionName}
            </div>
        )
    })
</Collapse>

这是这个过程的一个非常简单的应用。 这里要说明的一点是,如果你在一个对象数组上 map,你可以为每个数组元素渲染 JSX。 这可以是任何 JSX,甚至是您创建的组件。 这是非常强大的,因为这些组件可以拥有自己的 state 和行为,并且在折叠区域中也会如此。

此外,如果数组的那些内部对象也需要具有折叠功能,您可以在映射元素内执行相同的 JSX。 在这方面,天空是极限。

也许是这样的?

沙盒

import React, { useState } from "react";

const stepOne = () => "This is the step number 1";
const stepTwo = () => "This is the step number 2";
const stepTree = () => "This is the step number 3";

const objectOfFunctions = {
  stepOne,
  stepTwo,
  stepTree
};

const arrayOfStrings = [
  "stepOne",
  "stepTwo",
  "stepTree"
];

export default function App() {
  return <div>
    {
      arrayOfStrings.map( (e, index) => (
        <h3 key={index}>
          {objectOfFunctions[e]()}
        </h3>
      ))
    }
  </div>;
}

或者你可以在运行时使用这个组件将你的 String 解析为 JSX: react-jsx-parser

这样你就可以得到这样的字符串:

const str = 'This is a component rendered in runtime {Component}'

它会起作用的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM