首页 > 解决方案 > 文件夹内的动态文件不使用 React 和 preval.macro 读取

问题描述

我正在尝试构建一个应用程序,它将显示从我的 create-react-app 内的文件夹中读取的项目列表,它将读取并显示文件夹内的文件。

import preval from 'preval.macro';
import '../index.css'

const components = preval
    ` const fs = require('fs');
  const files = fs.readdirSync('src/atoms');
  module.exports = files;
`

const AtomList = () => {

    const [newFileName, setNewFileName] = useState('avatar');


    const fileUnderComponent = preval
        `   const fs = require('fs')
            const path = require('path');
            const file = fs.readFileSync('src/atoms/${newFileName}/${newFileName}.js');
            module.exports = file.toString();
        `;

    const setNewComponent = (componentName) => {
        setNewFileName(componentName)
    }

    const eachAtom = (component) => {
        return (
            <ul><li className="list-item-group" onClick={() => setNewComponent(component)}>{component}</li></ul>
        )
    }

    return (
        <div>
            <div className="list-group inlineBlock atomList width20">
                <div>List of Reusable Components</div>
                {components.map((component, i) => {
                    return eachAtom(component)
                })}
            </div>
            <div className="list-group inlineBlock atomDescription width80">
                {typeof fileUnderComponent === 'string' ? fileUnderComponent : null}
            </div>

        </div>
    )
}

export default AtomList

在上面的组件中,如果我将 newFileName 硬编码为“头像”,则文件的内容会呈现,但是当我在单击它们时切换组件时,newFileName 会发生变化,但 fileUnderComponent 不会呈现任何内容。

我想可能是由于 readFileSync 操作需要一些时间。我试过把它放在 setTimeout 但没有运气。

我哪里错了?

标签: node.jsreactjscreate-react-app

解决方案


preval 在构建时评估代码,因此无法在更新状态时运行它。以下用于提取文件内容以进行 preval 的代码可以正常工作。

const contentOfComponents = preval`
const fs = require("fs");
const files = fs.readdirSync("src/atoms");
const content = files.map(filename => {
  const fs = require("fs");
  const url = 'src/atoms/'+filename+'/'+filename+'.js';
  return fs.readFileSync(url).toString();
})
module.exports = content`;

您可以使用它contentOfComponents,它是文件内容的数组,通过将它们映射到您的components数组,然后在单击文件名时显示适当的内容。

合并上述更改后的问题代码

import React, { useState } from "react";
import preval from "preval.macro";
import shortid from "shortid";

const components = preval`
const fs = require("fs");
const files = fs.readdirSync("src/atoms");
module.exports = files`;

const contentOfComponents = preval`
const fs = require("fs");
const files = fs.readdirSync("src/atoms");
const content = files.map(filename => {
  const fs = require("fs");
  const url = 'src/atoms/'+filename+'/'+filename+'.js';
  return fs.readFileSync(url).toString();
})
module.exports = content`;

const AtomList = () => {
  const [fileUnderComponent, setFileUnderComponent] = useState(null);

  const setNewComponent = componentName => {
    const _index = components.indexOf(componentName);
    setFileUnderComponent(contentOfComponents[_index]);
  };

  const eachAtom = component => {
    return (
      <li
        key={shortid.generate()}
        className="list-item-group"
        onClick={() => setNewComponent(component)}
      >
        {component}
      </li>
    );
  };

  return (
    <div>
      <div className="list-group inlineBlock atomList width20">
        <div>List of Reusable Components</div>
        <ul>
          {components.map(component => {
            return eachAtom(component);
          })}
        </ul>
      </div>
      <div className="list-group inlineBlock atomDescription width80">
        {typeof fileUnderComponent === "string" ? fileUnderComponent : null}
      </div>
    </div>
  );
};

export default AtomList;

此外,您的eachAtom 函数不需要返回<ul>.

丢弃!这是第一印象

这可能是语法错误。在您的行const file = fs.readFileSync('src/atoms/${newFileName}/${newFileName}.js');中,您确定您使用的是引号而不是单引号吗?

这可能会解决它:

const file = fs.readFileSync(`src/atoms/${newFileName}/${newFileName}.js`);

反引号键通常位于左上角 Esc 键下方和数字 1 键的左侧。


推荐阅读