Create React App:

  • homepage of reactjs: https://reactjs.org/
  • click “Get Started” -> choose “Create a New React App” on the right menu

image.png

The structure of twittme-web is like:
image.png
we mainly focus on /twittme-web/src/App.js

Understanding Functional Components:

  • to start development in reactjs:

    1. [root@localhost Twittme]# cd twittme-web/
    2. [root@localhost twittme-web]# npm start

    but because I use virtualbox and remote access, so I have a forwarding setting
    image.png
    and I apply

    1. [root@localhost twittme-web]# npm start 0.0.0.0:3000

    Meanwhile, runserver of Twittme.
    Then access http://localhost:30/
    image.png

  • as the page above, take a look at /twittme-web/src/App.js ```javascript //import React from ‘react’; import React, {useEffect, useState} from ‘react’; //new import logo from ‘./logo.svg’; import ‘./App.css’;

function App() {

const [tweets, setTweets] = useState([{content: 123}]) //new

return (

logo

Edit src/App.js and save to reload.

  1. <!--new-->
  2. <p>
  3. {tweets.map((tweet, index)=>{
  4. return <li>{tweet.content}</li>
  5. })}
  6. </p>
  7. <a
  8. className="App-link"
  9. href="https://reactjs.org"
  10. target="_blank"
  11. rel="noopener noreferrer"
  12. >
  13. Learn React
  14. </a>
  15. </header>
  16. </div>

); }

export default App;

  1. back to react app page:![image.png](https://cdn.nlark.com/yuque/0/2020/png/1243266/1593198283756-5bbac67f-5e8a-42fb-ad57-e94106a1737b.png#align=left&display=inline&height=498&margin=%5Bobject%20Object%5D&name=image.png&originHeight=996&originWidth=1908&size=121305&status=done&style=none&width=954)<br />and "123" is correctly printed.
  2. - try use another pattern in /twittme-web/src/App.js
  3. ```javascript
  4. //const [tweets, setTweets] = useState([{content: 123}])
  5. const [tweets, setTweets] = useState([])
  6. /* how to declare a function
  7. const performLookup = () => {
  8. ...
  9. }
  10. or
  11. function performLookup () {
  12. ...
  13. }
  14. */
  15. useEffect(() => { // new
  16. const tweetItems = [{"content": 123}, {"content": "Hello World"}]
  17. setTweets(tweetItems)
  18. }, [])

see reactjs page
image.png

Ajax lookup via XHR in React.js:

  • copy loadTweets() from template home.html to App.js and modify it to fit react.js
  • apply it in App() ```javascript import React, {useEffect, useState} from ‘react’; import logo from ‘./logo.svg’; import ‘./App.css’;

function loadTweets(callback){ const xhr = new XMLHttpRequest() const method = ‘GET’ const url = “http://localhost:8000/api/tweets/“ const responseType = ‘json’

xhr.responseType = responseType xhr.open(method, url) xhr.onload = function() { callback(xhr.response, xhr.status) } xhr.onerror = function (e) { console.log(e) callback({“message”: “The request was an error”}, 400) //when status 400, callback “The request was an error” } xhr.send() }

function App() {

const [tweets, setTweets] = useState([])

useEffect(() => { const myCallback = (response, status) => { console.log(response, status) if (status === 200){ setTweets(response) } else { //if status not 200, alert “There was an error” alert(“There was an error”) } } loadTweets(myCallback) //const tweetItems = [{“content”: 123}, {“content”: “Hello World”}] //setTweets(tweetItems) }, [])

  1. //...

}

export default App;

  1. to test, access [http://localhost:30/](http://localhost:30/) after run the reactjs development server.<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1243266/1593206670286-eef9ea07-7574-496d-9871-a964c33a5db1.png#align=left&display=inline&height=460&margin=%5Bobject%20Object%5D&name=image.png&originHeight=921&originWidth=1784&size=107770&status=done&style=none&width=892)<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1243266/1593206705666-b1d7ed4d-1b8a-4d8c-8632-a4586588e95a.png#align=left&display=inline&height=478&margin=%5Bobject%20Object%5D&name=image.png&originHeight=956&originWidth=1892&size=168117&status=done&style=none&width=946)<br />So that the current status is apparently 400.
  2. <a name="RnHDl"></a>
  3. ### Handling CORS and Invalid HOST_HEADER in Django:
  4. - install django-cors-headers
  5. ```javascript
  6. pip install django-cors-headers
  7. # or pip3 for python3
  • about django-cors-headers: https://pypi.org/project/django-cors-headers/

    • “django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS).”
  • in /Twittme/settings.py ```python INSTALLED_APPS = [

    ‘corsheaders’, # new

    ]

MIDDLEWARE = [

  1. # ...
  2. 'corsheaders.middleware.CorsMiddleware', # new
  3. # ...

]

CORS_ORIGIN_ALLOW_ALL = True # any website has access to my api CORS_URLS_REGEX = r’^/api/.*$’

  1. For CORS setting, actually it's more safe to use methods like whitelist to restrict malicious accesses.
  2. - I realized cause I have a remote port forwarding, so a change in App.js
  3. ```javascript
  4. function loadTweets(callback){
  5. //...
  6. //const url = "http://localhost:8000/api/tweets/"
  7. const url = "http://localhost:80/api/tweets
  8. //...
  9. }

To test, runserver and start reactapp:
image.png
And reactjs page includes all tweet contents we have.

Functional Components in React:

  • still in /twittme-web/src/App.js, add a Tweet() components that includes format.
  • Then apply it.
  • another detail,

    cannot be a descendent of

    so change that pair of

    into

    1. function Tweet(props) {
    2. const {tweet} = props
    3. const className = 'col-10 mx-auto col-md-6'
    4. return <div className={className}>
    5. <p>{tweet.id} - {tweet.content}</p>
    6. </div>
    7. }
    8. //...
    9. //<p>
    10. <div>
    11. {//tweets.map((tweet, index) => {
    12. tweets.map((item, index) => {
    13. //return <li>{tweet.content}</li>
    14. return <Tweet tweet={item} key={`${index}-{item.id}`}/>
    15. })}
    16. //</p>
    17. </div>
    18. //...

    to test runserver and npm start
    image.png
    so all shown tweets have changed fonts and keys(indexes).

  • another modification: allow webpage to pass format

  • if no passed format, setup a default one,

    1. function Tweet(props) {
    2. const {tweet} = props
    3. //const className = 'col-10 mx-auto col-md-6'
    4. const className = props.className ? props.className : 'col-10 mx-auto col-md-6' //default format
    5. return <div className={className}>
    6. <p>{tweet.id} - {tweet.content}</p>
    7. </div>
    8. }
    9. //...
    10. <div>
    11. {tweets.map((item, index) => {
    12. //return <Tweet tweet={item} key={`${index}-{item.id}`}/>
    13. return <Tweet tweet={item} key={`${index}-{item.id}`} className='my-5 py-5 border bg-white text-dark'/>
    14. })}
    15. </div>
    16. //...
  • Then to make sure the passed font is applied, add a white background for tweets to emphasize text-dark.

  • add Bootstrap CSS before title in /twittme-web/public/index.html
    1. <!-- ... -->
    2. <!-- Bootstrap CSS -->
    3. <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    4. <title>React App</title>
    5. <!-- ... -->
    refresh
    image.png
    the rendering is successful.