LoginSignup
1
2

More than 5 years have passed since last update.

React-Reduxでajaxを呼ぶ

Last updated at Posted at 2018-03-11

TODOListサンプルコードを参考にしながら、ajaxを呼ぶのを書いてみる。

プロジェクトはcreate-react-appを使用して作成する

create-react-app Test
cd ./Test
npm install --save redux
npm install --save jquery
npm install --save material-ui@1.0.0-beta.30

とりあえず適当なjson形式のファイルをajaxで取得して表示するようなのを書いてみました。

自動生成されたindex.jsを書き換えていきます。
本来なら機能ごとにファイル分割するべきですが、
まずは動作確認用なので1ファイルで全部書いてしまいます。

material-uiで少し見た目もよくしてみた

index.js
import React from 'react';
import {render} from 'react-dom';
import './index.css';
import registerServiceWorker from './registerServiceWorker';
import { createStore } from 'redux';
import $ from 'jquery';
import Reboot from 'material-ui/Reboot';
import AppBar from 'material-ui/AppBar';
import Toolbar from 'material-ui/Toolbar';
import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button';
import Checkbox from 'material-ui/Checkbox';
import List, {ListItem, ListItemText} from 'material-ui/List';
import Table, { TableBody, TableCell, TableHead, TableRow } from 'material-ui/Table';

const initialState = {
  tasks: []
};

function tasksReducer(state = initialState, action){
  switch(action.type){
    case 'INPUT_TASK':
      return {
        ...state,
        task : action.payload.task
      }
    case 'ADD_TASK':
      return{
        ...state,
        tasks: state.tasks.concat([action.payload.task])
      };
    default:
      return state;
  }
}

const store = createStore(tasksReducer);


const addTask = (task) => ({
  type:'ADD_TASK',
  payload:{
    task,
  }
});


function TodoApp({ store }){
  const { tasks } = store.getState();
  return  (
    <div>
      <Reboot />
      <AppBar position="static">
      <Toolbar style={{backgroundColor: '#ffd699',}}>
        <Typography type="title" color="inherit" style={{color:"white"}}>
          Sample
        </Typography>
      </Toolbar>
      </AppBar>
      <div style={{padding:'16px'}} />
      <Button raised color="primary" type="button" onClick={() => clickButton()}>実行</Button>

      <Table>
        <TableHead>
          <TableRow>
            <TableCell>#</TableCell>
            <TableCell numeric>No.</TableCell>
            <TableCell numeric>menu</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {
            tasks.map(function(item,i){
              return (
                <TableRow key={i}>
                  <TableCell style={{width:'48px'}}>
                  <Checkbox/>
                  </TableCell>
                  <TableCell>{i}</TableCell>
                  <TableCell numeric>{`${item}`}</TableCell>

                </TableRow>
              );
            })
          }
        </TableBody>
      </Table>
    </div>
  );
}

function clickButton(){
  const { task, tasks } = store.getState();

  $.ajax({
    url: './test.json',
    type: 'GET',
    dataType: 'text',
    data: "",
    timeout: 5000,
    })
    .done(function(data){
      var jsonData = JSON.parse(data);
      for( var val in jsonData){
        store.dispatch(addTask(jsonData[val]));
      }

    })
    .fail(function() {
        // 通信失敗時の処理を記述
        store.dispatch(addTask("fail."));
  });
}

function renderApp(store){
  render(
    <TodoApp store={store} />,
    document.getElementById('root')
  );
}

store.subscribe(() => renderApp(store));
renderApp(store);

registerServiceWorker();

package.json
{
  "name": "Test",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "jquery": "^3.3.1",
    "material-ui": "^1.0.0-beta.30",
    "react": "^16.2.0",
    "react-dom": "^16.2.0",
    "react-scripts": "1.1.1",
    "redux": "^3.7.2"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

ファイルを作って格納しておいて

npm start

↑で作ったのをファイルで分割してみます。

最終的なファイル構成的にはこのようにする
│ index.css
│ index.js
│ logo.svg
│ registerServiceWorker.js
├─actions
│ tasks.js
├─components
│ TodoApp.js

├─containers
│ TodoApp.js
├─reducers
│ tasks.js

actions/tasks.js
export const addTask = (tasks) => ({
  type:'ADD_TASK',
  payload:{
    tasks,
  }
});
containers/TodoApp.js
import {connect} from 'react-redux'
import TodoApp from '../components/TodoApp.js';
import {addTask} from '../actions/tasks.js';

function mapStateToProps({task, tasks}){
  return {
    tasks,
  };
}

function mapDispatchToProps(dispatch){
  return {
    addTask(tasks){
      dispatch(addTask(tasks));
    }
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp);
components/TodoApp.js
import React from 'react';
import $ from 'jquery';
// import Reboot from 'material-ui/Reboot';
import AppBar from 'material-ui/AppBar';
import Toolbar from 'material-ui/Toolbar';
import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button';
import Checkbox from 'material-ui/Checkbox';
import Table, { TableBody, TableCell, TableHead, TableRow } from 'material-ui/Table';


function clickButton(addTask){
  $.ajax({
    url: './test.json',
    type: 'GET',
    dataType: 'text',
    data: "",
    timeout: 5000,
    })
    .done(function(data){
      var jsonData = JSON.parse(data);

      for( var val in jsonData){
        addTask(jsonData[val]);
      }

    })
    .fail(function() {
        // 通信失敗時の処理を記述
        addTask("fail.");
  });
}

export default function TodoApp({ tasks,inputTask,addTask }){

  return  (
    <div>
      <AppBar position="static">
      <Toolbar style={{backgroundColor: '#ffd699',}}>
        <Typography type="title" color="inherit" style={{color:"white"}}>
          Sample
        </Typography>
      </Toolbar>
      </AppBar>
      <div style={{padding:'16px'}} />
    <Button variant="raised" color="primary"  type="button" onClick={() => clickButton(addTask)}>実行</Button>

      <Table>
        <TableHead>
          <TableRow>
            <TableCell>#</TableCell>
            <TableCell numeric>No.</TableCell>
            <TableCell numeric>menu</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {

            tasks.map(function(item,i){
              return (
                <TableRow key={i}>
                  <TableCell style={{width:'48px'}}>
                  <Checkbox/>
                  </TableCell>
                  <TableCell>{i}</TableCell>
                  <TableCell numeric>{`${item}`}</TableCell>
                </TableRow>
              );
            })
          }
        </TableBody>
      </Table>
    </div>
  );
}
reducers/tasks.js
const initialState = {
  tasks: []
};

export default function tasksReducer(state = initialState, action){
  switch(action.type){
    case 'ADD_TASK':
      return{
        ...state,
        tasks: state.tasks.concat([action.payload.tasks])
      };
    default:
      return state;
  }
}
index.js
import React from 'react';
import {Provider} from 'react-redux';
import { createStore } from 'redux';
import {render} from 'react-dom';
import tasksReducer from './reducers/tasks.js';
import TodoApp from './containers/TodoApp.js';

import registerServiceWorker from './registerServiceWorker';


const store = createStore(tasksReducer);

function renderApp(store){
  render(
    <Provider store={store}>
      <TodoApp />
    </Provider>,
    document.getElementById('root')
  );
}

renderApp(store);

registerServiceWorker();
package.json
{
  "name": "test",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "jquery": "^3.3.1",
    "material-ui": "^1.0.0-beta.30",
    "react": "^16.2.0",
    "react-dom": "^16.2.0",
    "react-redux": "^5.0.7",
    "react-scripts": "1.1.1",
    "redux": "^3.7.2"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2