Escher-js / TaskBucket

0 stars 0 forks source link

React bootstrap #6

Closed psmuler closed 1 year ago

psmuler commented 1 year ago

オッケーです。次のタスクである、「react bootstrapの繋ぎこみ」にいきましょう!react bootstrapとしてShards-Dashboard-Lite-React-1.0.0を用います。

psmuler commented 1 year ago

Shards Dashboard Lite Reactをプロジェクトに組み込んで使用する手順を説明します。

  1. 最初に、プロジェクトのルートディレクトリで、Shards Dashboard Lite ReactのZIPファイルをダウンロードして解凍します。ダウンロードはこちらから行えます。解凍後、srcディレクトリ内にshards-dashboardディレクトリが作成されます。

  2. 次に、プロジェクトのルートディレクトリで以下のコマンドを実行し、必要なパッケージをインストールします。

npm install --save bootstrap@4.6.0
npm install --save shards-ui@2.0.2
  1. プロジェクトのsrcディレクトリにあるindex.jsファイルを開き、以下の2行を追加して、Shards Dashboard Lite ReactのCSSをインポートします。
import 'bootstrap/dist/css/bootstrap.min.css';
import 'shards-ui/dist/css/shards.min.css';
  1. この時点で、Shards Dashboard Lite Reactのコンポーネントがプロジェクトで利用できるようになります。解凍したshards-dashboardディレクトリ内のコンポーネントを必要に応じてインポートし、既存のコンポーネントを置き換えるか、新しいコンポーネントを追加してカスタマイズします。

  2. 必要に応じて、プロジェクトのpublicディレクトリにあるfavicon.icoファイルやmanifest.jsonファイルを、shards-dashboard/publicディレクトリ内の対応するファイルで置き換えます。これにより、Shards Dashboard Liteのアイコンやアプリケーション名が適用されます。

これで、Shards Dashboard Lite Reactがプロジェクトに組み込まれ、カスタマイズが可能になりました。必要に応じて、Shards Dashboard Lite Reactのコンポーネントやスタイルを使用して、アプリケーションの見た目を調整してください。

psmuler commented 1 year ago
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: task-manager@0.1.0
npm ERR! Found: react@18.2.0
npm ERR! node_modules/react
npm ERR!   react@"^18.2.0" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.6.3" from shards-react@1.0.3
npm ERR! node_modules/shards-react
npm ERR!   shards-react@"1.0.3" from the root project
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
psmuler commented 1 year ago

このエラーは、プロジェクトで使用しているReactのバージョン(18.2.0)が、Shards Reactが必要とするReactのバージョン(^16.6.3)と互換性がないために発生しています。この問題を解決する方法はいくつかありますが、2つの一般的な方法を紹介します。

方法1: --legacy-peer-depsオプションを使用してインストールする この方法では、互換性の問題を無視してShards Reactをインストールします。ただし、予期しない問題が発生する可能性があるため、注意が必要です。

npm install --save shards-react@1.0.3 --legacy-peer-deps

方法2: Reactのバージョンをダウングレードする この方法では、プロジェクトのReactのバージョンをShards Reactがサポートするバージョンにダウングレードします。以下のコマンドを実行して、ReactとReactDOMのバージョンを16.14.0に変更してください。

npm uninstall react react-dom
npm install --save react@16.14.0 react-dom@16.14.0

ダウングレードが完了したら、再度以下のコマンドを実行してShards Reactをインストールしてください。

npm install --save shards-react@1.0.3

どちらの方法でも、Shards Reactが正常にインストールされ、プロジェクトで使用できるようになるはずです。ただし、方法1を選択した場合は、Shards Reactが最新のReactバージョンで正しく動作するかどうかを確認することが重要です。

psmuler commented 1 year ago
npm ERR! node_modules/@testing-library/react
npm ERR!   @testing-library/react@"^13.4.0" from the root project
npm ERR! 
npm ERR! Conflicting peer dependency: react@18.2.0
npm ERR! node_modules/react
npm ERR!   peer react@"^18.0.0" from @testing-library/react@13.4.0
npm ERR!   node_modules/@testing-library/react
npm ERR!     @testing-library/react@"^13.4.0" from the root project
psmuler commented 1 year ago

このエラーは、@testing-library/reactがReactのバージョン18以降を必要としている一方で、先程Reactのバージョンを16.14.0にダウングレードしたために発生しています。これを解決するには、@testing-library/reactを使用する代わりに、Reactのバージョン16に対応する適切なテストライブラリをインストールすることをお勧めします。

まず、@testing-library/reactをアンインストールします。

npm uninstall @testing-library/react

次に、Reactのバージョン16に対応する@testing-library/reactのバージョンをインストールします。バージョン11.2.7は、React 16と互換性があります。

npm install --save @testing-library/react@11.2.7

これで、React 16と互換性がある@testing-library/reactのバージョンがインストールされ、エラーが解消されるはずです。

psmuler commented 1 year ago

ERROR in ./src/index.js 5:0-40 Module not found: Error: Can't resolve 'react-dom/client' in '/Users/ti/Documents/code/artificial_todo/task-manager/src'

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'shards-ui/dist/css/shards.min.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
psmuler commented 1 year ago

react-dom/clientは、React 18以降で導入された新しい機能です。React 16を使用しているため、この機能を利用することはできません。そのため、index.jsimport ReactDOM from 'react-dom/client';を以下のように変更してください。

import ReactDOM from 'react-dom';

また、ReactDOM.createRootもReact 18で導入された新しいAPIです。React 16では、ReactDOM.renderを使用してアプリケーションをレンダリングする必要があります。

以下のようにindex.jsを変更してください。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'shards-ui/dist/css/shards.min.css';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

これで、React 16で正しく動作するようになります。

psmuler commented 1 year ago

エラーがより根本的な部分に差し掛かったため、一度変更を破棄してbootstrap導入ブランチを枝分かれさせた時点にコミットを戻したいです。

psmuler commented 1 year ago

Gitを使用して変更を破棄し、以前のコミットに戻すことができます。まず、現在の変更を破棄する必要があります。これは、以下のコマンドを実行して行うことができます。

git reset --hard HEAD

次に、ブートストラップ導入ブランチを枝分かれさせた時点のコミットに戻ります。これを行うには、まずそのコミットのハッシュを見つける必要があります。以下のコマンドを実行して、コミットログを表示します。

git log

コミットログには、コミットの一覧とそれぞれの詳細が表示されます。ブートストラップ導入ブランチを枝分かれさせた時点のコミットを見つけ、そのコミットハッシュ(例: abcdef123456...)をコピーします。

コミットハッシュをコピーしたら、以下のコマンドを実行して、そのコミットに戻ります。<commit-hash>の部分を、先ほどコピーしたコミットハッシュに置き換えてください。

git reset --hard <commit-hash>

これで、ブートストラップ導入ブランチを枝分かれさせた時点のコミットに戻ることができます。ただし、これらのコマンドは変更を破棄するため、必ずバックアップを取ってから実行してください。

psmuler commented 1 year ago

------reset. back to:--------

Shards Dashboard Lite Reactをプロジェクトに組み込んで使用する手順を説明します。

  1. 最初に、プロジェクトのルートディレクトリで、Shards Dashboard Lite ReactのZIPファイルをダウンロードして解凍します。ダウンロードはこちらから行えます。解凍後、srcディレクトリ内にshards-dashboardディレクトリが作成されます。
  2. 次に、プロジェクトのルートディレクトリで以下のコマンドを実行し、必要なパッケージをインストールします。
npm install --save bootstrap@4.6.0
npm install --save shards-ui@2.0.2
  1. プロジェクトのsrcディレクトリにあるindex.jsファイルを開き、以下の2行を追加して、Shards Dashboard Lite ReactのCSSをインポートします。
import 'bootstrap/dist/css/bootstrap.min.css';
import 'shards-ui/dist/css/shards.min.css';
  1. この時点で、Shards Dashboard Lite Reactのコンポーネントがプロジェクトで利用できるようになります。解凍したshards-dashboardディレクトリ内のコンポーネントを必要に応じてインポートし、既存のコンポーネントを置き換えるか、新しいコンポーネントを追加してカスタマイズします。
  2. 必要に応じて、プロジェクトのpublicディレクトリにあるfavicon.icoファイルやmanifest.jsonファイルを、shards-dashboard/publicディレクトリ内の対応するファイルで置き換えます。これにより、Shards Dashboard Liteのアイコンやアプリケーション名が適用されます。

これで、Shards Dashboard Lite Reactがプロジェクトに組み込まれ、カスタマイズが可能になりました。必要に応じて、Shards Dashboard Lite Reactのコンポーネントやスタイルを使用して、アプリケーションの見た目を調整してください。

psmuler commented 1 year ago

Shards Dashboardのコンポーネントを使用して、タスクをカード形式で表示し、クリックするとタスクの詳細がポップアップするように実装します。

  1. TaskTable.jsを以下のように書き換えます。Shards DashboardのCardCardBodyコンポーネントを使用してカード形式でタスクを表示します。
import React from 'react';
import { Card, CardBody } from 'shards-react';

const TaskTable = ({ tasks }) => {
  const renderTask = (task) => {
    return (
      <Card className="task-card" onClick={() => alert(`詳細: ${task.detail}`)}>
        <CardBody>
          <p className="task-name">{task.name}</p>
        </CardBody>
      </Card>
    );
  };

  return (
    <table className="task-table">
      <tbody>
        {tasks.map((row, i) => (
          <tr key={i}>
            {row.map((cell, j) => (
              <td key={j}>
                {cell.map((task) => (
                  <React.Fragment key={task.name}>{renderTask(task)}</React.Fragment>
                ))}
              </td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
};

export default TaskTable;
  1. カード形式のタスクとポップアップのスタイルを調整するために、App.cssを以下のように更新します。
.task-table {
  width: 100%;
  height: 100%;
  border-collapse: collapse;
}

.task-table td {
  width: 20%;
  height: 20%;
  padding: 10px;
  vertical-align: top;
}

.task-card {
  width: 100%;
  cursor: pointer;
}

.task-name {
  margin: 0;
}

これで、タスクがカード形式で表示され、クリックするとタスクの詳細がポップアップします。ポップアップの実装は、alert()を使用していますが、必要に応じてカスタムモーダルやツールチップを使用することができます。

psmuler commented 1 year ago

react-dom.development.js:1822

Warning: Each child in a list should have a unique "key" prop.

Check the render method of TaskTable. See https://reactjs.org/link/warning-keys for more information. at TaskTable (http://localhost:3000/main.a1bf5319390152289cf0.hot-update.js:27:5) at main at div at App 全文を記載するのは大変なので、適宜わかりやすく省略して記述してください

psmuler commented 1 year ago

すみません、TaskTableコンポーネントのrenderTask関数で、Reactのキーを適切に設定することを見落としていました。以下のように修正して、警告が表示されないようにします。

  1. TaskTable.jsrenderTask関数を以下のように書き換えます。
const renderTask = (task) => {
  return (
    <Card key={task.name} className="task-card" onClick={() => alert(`詳細: ${task.detail}`)}>
      <CardBody>
        <p className="task-name">{task.name}</p>
      </CardBody>
    </Card>
  );
};

これで、keyプロパティがCardコンポーネントに適切に設定され、警告が表示されなくなります。

psmuler commented 1 year ago

react-jsx-dev-runtime.development.js:87 Warning: Each child in a list should have a unique "key" prop. Check the render method of TaskTable. See https://reactjs.org/link/warning-keys for more information. at TaskTable (http://localhost:3000/static/js/bundle.js:133:5) at main at div at App

psmuler commented 1 year ago

失礼しました。React.Fragmentにもキーを設定する必要があります。以下のようにTaskTable.jsを修正してください。

import React from 'react';
import { Card, CardBody } from 'shards-react';

const TaskTable = ({ tasks }) => {
  const renderTask = (task) => {
    return (
      <Card key={task.name} className="task-card" onClick={() => alert(`詳細: ${task.detail}`)}>
        <CardBody>
          <p className="task-name">{task.name}</p>
        </CardBody>
      </Card>
    );
  };

  return (
    <table className="task-table">
      <tbody>
        {tasks.map((row, i) => (
          <tr key={i}>
            {row.map((cell, j) => (
              <td key={j}>
                {cell.map((task) => (
                  <React.Fragment key={task.name}>{renderTask(task)}</React.Fragment>
                ))}
              </td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
};

export default TaskTable;

これで、すべての子要素に適切なキーが設定され、警告が表示されなくなります。

psmuler commented 1 year ago

依然として同じエラーが出ます。考えられる候補と、より問題を切り分けるためにあなたが必要な情報の一覧をください。

psmuler commented 1 year ago

失礼しました。問題の切り分けのために、以下の情報が必要です:

  1. 現在のTaskTable.jsの全文
  2. 現在のApp.jsの全文
  3. エラーメッセージに表示されているコードの行番号を特定

以下は、問題の解決に役立つ可能性のある変更案です。

  1. まず、renderTask関数を削除し、TaskTable.jsreturn文の中で直接Cardコンポーネントをレンダリングします。
import React from 'react';
import { Card, CardBody } from 'shards-react';

const TaskTable = ({ tasks }) => {
  return (
    <table className="task-table">
      <tbody>
        {tasks.map((row, i) => (
          <tr key={i}>
            {row.map((cell, j) => (
              <td key={j}>
                {cell.map((task) => (
                  <Card key={task.name} className="task-card" onClick={() => alert(`詳細: ${task.detail}`)}>
                    <CardBody>
                      <p className="task-name">{task.name}</p>
                    </CardBody>
                  </Card>
                ))}
              </td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
};

export default TaskTable;
  1. それでも問題が解決しない場合は、TaskTable.jsreturn文を再度確認し、リスト内のすべての要素に一意のキーが設定されていることを確認してください。map()関数が使用されている部分では、keyプロパティが設定されている必要があります。

それでも問題が解決しない場合、現在のTaskTable.jsApp.jsのコードと、エラーメッセージの詳細をお知らせください。それによって、より具体的な解決策を提案できるかもしれません。

psmuler commented 1 year ago

1.現在のTaskTable.jsの全文 {省略}

  1. 現在のApp.jsの全文 {省略}

  2. エラーメッセージに表示されているコードの行番号を特定 エラーが発生しているのはTaskTable.jsではないかもしれません。 react-jsx-dev-runtime.development.js:87

なお提示された解決策1を行ったところ表示されるエラーが変化したので、必要であれば聞いてください。

psmuler commented 1 year ago

ありがとうございます。情報をもとに、再度TaskTable.jsの修正を行います。React.Fragmentが不要だと思われますので、それを削除しましょう。以下のように変更してください。

import React from 'react';
import { Card, CardBody } from 'shards-react';

const TaskTable = ({ tasks }) => {
  return (
    <table className="task-table">
      <tbody>
        {tasks.map((row, i) => (
          <tr key={i}>
            {row.map((cell, j) => (
              <td key={j}>
                {cell.map((task) => (
                  <Card key={task.name} className="task-card" onClick={() => alert(`詳細: ${task.detail}`)}>
                    <CardBody>
                      <p className="task-name">{task.name}</p>
                    </CardBody>
                  </Card>
                ))}
              </td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
};

export default TaskTable;

これにより、keyの問題が解決されるはずです。上記の修正後にまだ警告やエラーが発生する場合は、その内容をお知らせください。

psmuler commented 1 year ago

eck the render method of TaskTable. See https://reactjs.org/link/warning-keys for more information. at Card (http://localhost:3000/static/js/bundle.js:67528:25) at TaskTable (http://localhost:3000/static/js/bundle.js:133:5) at main at div at App

エラーメッセージのhttps://reactjs.org/link/warning-keysの詳細です Keeping list items in order with key Notice that all the sandboxes above show an error in the console:

Console Warning: Each child in a list should have a unique “key” prop. You need to give each array item a key — a string or a number that uniquely identifies it among other items in that array:

  • ...
  • Note JSX elements directly inside a map() call always need keys!

    Keys tell React which array item each component corresponds to, so that it can match them up later. This becomes important if your array items can move (e.g. due to sorting), get inserted, or get deleted. A well-chosen key helps React infer what exactly has happened, and make the correct updates to the DOM tree.

    Rather than generating keys on the fly, you should include them in your data:

    psmuler commented 1 year ago

    すみません、私の修正がまだ不十分でした。

    エラーの原因は、<Card>がリスト内で直接使われているため、それぞれの<Card>key属性が必要だということです。以下のようにコードを修正してみてください。

    import React from 'react';
    import { Card, CardBody } from 'shards-react';
    
    const TaskTable = ({ tasks }) => {
      return (
        <table className="task-table">
          <tbody>
            {tasks.map((row, i) => (
              <tr key={i}>
                {row.map((cell, j) => (
                  <td key={j}>
                    {cell.map((task) => (
                      <React.Fragment key={task.name}>
                        <Card className="task-card" onClick={() => alert(`詳細: ${task.detail}`)}>
                          <CardBody>
                            <p className="task-name">{task.name}</p>
                          </CardBody>
                        </Card>
                      </React.Fragment>
                    ))}
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
      );
    };
    
    export default TaskTable;

    上記の修正で<Card>要素を<React.Fragment>で囲み、<React.Fragment>key属性を追加しました。これでエラーが解決されるはずです。もしまだ問題があればお知らせください。

    psmuler commented 1 year ago

    依然としてエラーでした。私が提示している表形式でカードを入れるという仕様に少し無理があるのかもしれません。以下を満たしたいときに良いと思われる実装を提案してください。 ・タスクのurgencyとimportanceが一目でわかるように図示されている ・タスクのそれぞれをクリック可能で、クリックするとタスクの詳細が表示される html5のcanvasなどを使うと良いのでしょうか。あるいはshards-dashboardの要素で上記を実現可能なものがあれば教えてください。

    psmuler commented 1 year ago

    表形式で表示するのではなく、CSS Gridを利用してタスクを表示し、その位置によってurgencyimportanceを示すことができます。この方法では、矩形領域内にタスクを配置し、urgencyimportanceの値に応じてタスクの位置が変化します。

    以下は、CSS Gridを使用してタスクの表示を実装する方法です。

    まず、新しいコンポーネントTaskGrid.jsを作成し、以下のように実装します。

    import React from 'react';
    import { Card, CardBody } from 'shards-react';
    import './TaskGrid.css';
    
    const TaskGrid = ({ tasks }) => {
      const renderTask = (task) => (
        <Card key={task.name} className="task-card" onClick={() => alert(`詳細: ${task.detail}`)}>
          <CardBody>
            <p className="task-name">{task.name}</p>
          </CardBody>
        </Card>
      );
    
      const taskItems = tasks.flat().map((task) => {
        const gridRow = task.urgency;
        const gridColumn = task.importance;
        return (
          <div key={task.name} className="grid-item" style={{ gridRow, gridColumn }}>
            {renderTask(task)}
          </div>
        );
      });
    
      return <div className="task-grid">{taskItems}</div>;
    };
    
    export default TaskGrid;

    次に、TaskGrid.cssを作成し、以下のように記述します。

    .task-grid {
      display: grid;
      grid-template-columns: repeat(5, 1fr);
      grid-template-rows: repeat(5, 1fr);
      grid-gap: 1rem;
    }
    
    .grid-item {
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .task-card {
      cursor: pointer;
      width: 100%;
    }

    最後に、App.jsTaskTableの代わりにTaskGridを使用します。

    import React from 'react';
    import TaskGrid from './components/TaskGrid';
    import { jsonToTasks } from './utils/jsonToTasks';
    import jsonData from './data/tasks.json';
    import './App.css';
    
    // JSONデータを2次元配列に変換する
    const tasks = jsonToTasks(jsonData);
    
    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <h1>Task Manager</h1>
          </header>
          <main className="App-main">
            <TaskGrid tasks={tasks} />
          </main>
        </div>
      );
    }
    
    export default App;

    これで、タスクがCSS Grid内に配置され、urgencyimportanceの値に応じた位置に表示されるようになります。タスクをクリックすると、そのタスクの詳細が表示されます。

    psmuler commented 1 year ago

    ------reset with error------ 結局ブランチをリセットしたときにshards-dashboardを再インストールし忘れていたのが原因だった模様。 このissueは一旦閉じ、同じissueを立てることとする。

    psmuler commented 1 year ago

    issueにもブランチ機能欲しい。