I would like the wording used for the layout inside mainPage would change according to the language selected at component Header.jsx. However, change in Header.jsx could not pass to Header.jsx, therefore, noting is changed when clicking on the language selector.
import React, { useState, useEffect } from "react";
import Header from "../Resources/Components/Header";
import Footer from "../Resources/Components/Footer";
import {MainPageContext, useMainPageContext } from "../Resources/Hooks/mainPageContext";
import "./MainPage.css";
const MainPage = () => {
const context = useMainPageContext();
const {
language,
} = context;
useEffect(()=>{
console.log("is me hi!")
},[language])
const [introductionPage, setIntroductionPage] = useState(0);
console.log("language is", language)
//const [language, setLanguage]= useState(0);
//below is the script of the test description. 隨時可以加入新array做新language。
const renderLanguageSwitch= (language) => {
switch(language) {
case 0:
return ['測試開始','測試資料採集同意書'];
case 1:
return ['Test Start', 'Test Data Collection Agreement']
default:
return ['測試開始','測試資料採集同意書'];
}
};
const renderButtonSwitch= (language) => {
switch(language) {
case 0:
return ['我同意', '我拒絕'];
case 1:
return ['I agree', 'I disagree']
default:
return ['我同意', '我拒絕'];
}
};
return (
<div className="MainPage">
<Header />
<div
style={{
width: "100%",
height: "100vh",
backgroundColor: "#F5821F",
margin: "0",
}}
>
{introductionPage === 0 && (
<button
className="testStartBox"
onClick={() => {
setIntroductionPage(1);
}}
>
{renderLanguageSwitch(language)[0]}
</button>
)}
{introductionPage !== 0 && (
<div>
<div
className="testDescriptionBox"
onClick={() => {
setIntroductionPage(introductionPage + 1);
}}
>
{renderLanguageSwitch(language)[1]}
</div>
<div className="testAgreement">
</div>
</div>
)}
<div
className="buttonWrapper"
style={{ display: introductionPage === 1 ? "" : "none" }}
>
<button onClick={() => {
setIntroductionPage(introductionPage + 1);
}}> {renderButtonSwitch(language)[0]}</button>
<button onClick={() => {
setIntroductionPage(0);
}}>{renderButtonSwitch(language)[1]}</button>
</div>
</div>{" "}
<Footer />
</div>
);
};
export default MainPage;
There is a language selector on the component Header.jsx, I would like to change the language, then change the content of MainPage. However, it doesn't work.
import React from "react";
import { useMainPageContext } from "../Hooks/mainPageContext";
const Header = () => {
const context = useMainPageContext();
const {
language,
onSetLanguage,
} = context;
return (
<div className="header">
<h1
style={{
display: "flex",
flexFlow:"row",
alignItems:"center",
width: "calc(100% - 10%)",
height: "4vh",
}}
>
<div style={{display:"flex", color: "#F5821F",}}>
<img src={require("../Images/Logo.png")} style={{width:"50%", height:"7.5%", marginTop:"0vh"}} alt="image name"/>
<div style={{ top: "0", margin: "0vh", marginLeft:"2vw", width:" 100%", fontSize:"3vw"}}>中心</div>
</div>
<div><div style={{marginTop:"1vh", fontSize:"2vw"}} onClick={()=>{language===1? onSetLanguage(0):onSetLanguage(1);
}}>繁體/ English</div></div>
</h1>
</div>
);
};
export default Header;
I have changed the coding , so that it is a context variable passed to the mainPage.js, however, I have another problem, the missing transition key.
Here is my i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
i18n
.use(initReactI18next)
.init({
backend: {
loadPath: `/locales/{{lng}}/translation.json`,
parse: data => data,
},
lng: 'en',
fallbackLng: 'en',
debug: true,
resources: {
'en': {
translation: 'en',
},
'tw': {
translation: 'tw',
},
},
interpolation: {
escapeValue: false
}
});
export default i18n;
Here is the App.js
import React , { Component, Suspense , useState, useCallback} from 'react';
import { useTranslation, withTranslation, Trans ,I18nextProvider} from 'react-i18next';
import ReactDOM from "react-dom/client";
import{
createBrowserRouter, RouterProvider,BrowserRouter as Router
} from "react-router-dom";
import logo from './logo.svg';
import './App.css';
//Import the pages
import MainPage from "./MainPage/MainPage";
import A1SubjectPage1 from "./ASubject/A1SubjectPage1";
import B1ResearcherPage1 from "./BResearcher/B1ResearcherPage1";
import Header from './Resources/Components/Header';
// use hoc for class based components
class LegacyWelcomeClass extends Component {
render() {
const { t } = this.props;
return <h2>{t('title')}</h2>;
}
}
const Welcome = withTranslation()(LegacyWelcomeClass);
// Component using the Trans component
/*function MyComponent() {
return (
<Trans i18nKey="description.part1">
To get started, edit <code>src/App.js</code> and save to reload.
</Trans>
);
}
*/
// page uses the hook
function App() {
const { t, i18n } = useTranslation();
const [language, setLanguage] = useState('en');
const onSetLanguage = useCallback((lng) => {
setLanguage(lng);
}, []);
const router = createBrowserRouter([
{
path: "/",
element: <div><MainPage/></div>,
},
{
path: "/mainPage",
element: <div>wowkdjfkdow<MainPage /></div>,
},
{
path: "/A1SubjectPage1",
element: <div>puripuri<A1SubjectPage1 /></div>,
},
{
path: "/B1ResearcherPage1",
element: <div>ReRe<B1ResearcherPage1 /></div>,
},
]);
ReactDOM.createRoot(document.getElementById("root")).render(
<I18nextProvider i18n={i18n}>
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
</I18nextProvider>
);
let routes;
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> This is a project
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Hello World Again and Again
</a>
</header>
<Router>
<div className="App-intro">
</div>
<main>{routes}</main>
</Router>
</div>
);
}
export default App;
Here is the mainPage.js
import React, { useState, useEffect, Component , Suspense, useCallback} from "react";
import Header from "../Resources/Components/Header";
import Footer from "../Resources/Components/Footer";
import { useTranslation, withTranslation, Trans } from 'react-i18next';
import {MainPageContext, useMainPageContext } from "../Resources/Hooks/mainPageContext";
import "./MainPage.css";
class LegacyWelcomeClass extends Component {
render() {
const { t } = this.props;
return <h2>{t('title')}</h2>;
}
}
const Welcome = withTranslation()(LegacyWelcomeClass);
const MainPage = () => {
const { t, i18n } = useTranslation();
const context = useMainPageContext();
const [language, setLanguage] = useState('tw');
const onSetLanguage = useCallback((lng) => {
setLanguage(lng);
}, []);
const [introductionPage, setIntroductionPage] = useState(0);
//const [language, setLanguage]= useState(0);
//below is the script of the test description. 隨時可以加入新array做新language。
const renderLanguageSwitch = () => {
return [t('testStart'), t('testAgreement')];
};
const renderButtonSwitch = () => {
return [t('agree'), t('disagree')];
};
return (
<div className="MainPage">
<Trans i18nKey="title">
<h2>{t('title')}</h2>
</Trans>
<Header onSetLanguage={onSetLanguage} />
<div
style={{
width: "100%",
height: "100vh",
backgroundColor: "#F5821F",
margin: "0",
}}
>
{introductionPage === 0 && (
<button
className="testStartBox"
onClick={() => {
setIntroductionPage(1);
}}
>
{t('agree')}, {t('disagree')}
</button>
)}
{introductionPage !== 0 && (
<div>
<div
className="testDescriptionBox"
onClick={() => {
setIntroductionPage(introductionPage + 1);
}}
>
{t('description')}
</div>
<div className="testAgreement">
</div>
</div>
)}
<div
className="buttonWrapper"
style={{ display: introductionPage === 1 ? "" : "none" }}
>
<button onClick={() => {
setIntroductionPage(introductionPage + 1);
}}> {t('description')}</button>
<button onClick={() => {
setIntroductionPage(0);
}}>{t('agreement')}</button>
</div>
</div>{" "}
<Footer />
</div>
);
};
export default MainPage;
Here is the Header.js
import React, { useCallback, useContext } from "react";
import { useMainPageContext } from "../Hooks/mainPageContext";
import { useTranslation } from 'react-i18next';
const Header = () => {
const { t, i18n } = useTranslation();
const context = useMainPageContext();
const { onSetLanguage } = context;
const toggleLanguage = useCallback((lng) => {
i18n.changeLanguage(lng);
onSetLanguage(lng);
}, [i18n, onSetLanguage]);
const currentLanguage = i18n.language;
return (
<div className="header">
<h1
style={{
display: "flex",
flexFlow:"row",
alignItems:"center",
width: "calc(100% - 10%)",
height: "4vh",
backgroundColor: "white",
paddingTop:"0",
padding: "2.5%",
paddingLeft: "5%",
paddingRight: "5%",
justifyContent:"space-between"
}}
>
<div style={{display:"flex", color: "#F5821F",}}>
<img src={require("../Images/cmghLogo.png")} style={{width:"50%", height:"7.5%", marginTop:"0vh"}} alt="logo"/>
<div style={{ top: "0", margin: "0vh", marginLeft:"2vw", width:" 100%", fontSize:"3vw"}}>中心</div>
</div>
<div>
<header>
<button onClick={() => toggleLanguage('en')} disabled={currentLanguage === 'en'}>English</button>
<button onClick={() => toggleLanguage('tw')} disabled={currentLanguage === 'tw'}>中文</button>
</header>
</div>
</h1>
</div>
);
};
export default Header;
The i18n.js did not set properly.
so that failed to read the translation key-value pair.
After I changed to install and using "i18next-http-backend" plugin, modified the i18n.js, the problem is fixed as the following:
import i18n from 'i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';
i18n
// load translation using http -> see /public/locales
// learn more: https://github.com/i18next/i18next-http-backend
.use(Backend)
// detect user language
// learn more: https://github.com/i18next/i18next-browser-languageDetector
.use(LanguageDetector)
// pass the i18n instance to react-i18next.
.use(initReactI18next)
// init i18next
// for all options read: https://www.i18next.com/overview/configuration-options
.init({
fallbackLng: 'en',
debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
});
export default i18n;
I try to learn React JS, however, I stumbled over a problem I can't solve. I try to use an API to get a value of something and show the value as a simple text, but the text is not updating even tho the Data gets correctly log in console.
The Code of my App.js is
import React, { Component } from "react";
import { Button } from "#material-ui/core";
import { Image } from "react-bootstrap";
import albedo from "#albedo-link/intent/lib/albedo.intent";
import albedologo from "./albedo.png";
class LogInWithAlbedo extends Component {
constructor(props) {
super(props);
this.state = {
value: null
};
}
Albedo() {
albedo.publicKey({}).then((res) => {
const { intent, pubkey, signature, signed_message } = res;
console.log({ intent, pubkey, signature, signed_message });
this.setState((currentState) => {
return { value: pubkey };
});
});
}
render() {
const { pubkey } = this.state;
return (
<div>
<div>
<Button
style={{ width: "207px", height: "40px" }}
variant="contained"
color="default"
onClick={this.Albedo.bind(this)}
>
Login With <Image style={{ width: "55px" }} src={albedologo} />
</Button>
<h2>It is {pubkey}.</h2>
</div>
</div>
);
}
}
export default LogInWithAlbedo;
You can also see it here:
https://codesandbox.io/s/vigilant-star-ntqv7
I have created a function which fetches data from API and send a response of userDetail, which has been created in context. and function has been called in Dashboard component by importing context. And when user clicks button it render userData.
I am tried testing to check function has been called once or not, after click. but not able to achieve it.
Context Page
here userDataFunc is created .
import React, { Component, createContext } from "react";
import axios from "axios";
export const Contx = createContext();
export class ConProvider extends Component {
state = {
userData: []
};
userDataFunc = async () => {
await axios(`https://jsonplaceholder.typicode.com/users`)
.then((res) => {
if (res.status === 200) {
this.setState({
userData: res.data
});
}
})
.catch((err) =>
this.setState({
userDataerror: err
})
);
};
render() {
console.log(this.state.coin);
return (
<Contx.Provider
value={{
...this.state,
userDataFunc: this.userDataFunc
}}
>
{this.props.children}
</Contx.Provider>
);
}
}
Dashboard Component
Here Function and userdata state has been imported from context
import React, { useContext } from "react";
import { Contx } from "../ContextApi";
export default function Dashboard() {
const { userDataFunc, userData } = useContext(Contx);
return (
<div
style={{ height: "100vh", backgroundColor: "#151515" }}
className="d-flex justify-content-center align-items-center"
>
<button data-testid="renderData" onClick={userDataFunc}>
Render Data
</button>
<div
style={{
overflowY: "auto",
margin: "4px",
border: "2px solid",
padding: "12px",
height: "80vh"
}}
data-testid="tableData"
>
{userData.map((i) => {
return (
<h5 key={i.id} style={{ color: "#fff" }}>
{i.name}
</h5>
);
})}
</div>
</div>
);
}
Dashboard Test File
// import React from "react";
import { fireEvent, render } from "#testing-library/react";
import axiosMock from "axios";
import Dashboard from "./Dashboard";
import { Contx } from "../ContextApi";
jest.mock("axios");
it("Api Called", () => {
const { getByTestId } = render(
<Contx>
<Dashboard />
</Contx>
);
const renderButton = getByTestId("userData");
fireEvent.click(renderButton);
expect(Dashboard.userDataFunc()).toHaveBeenCalledTimes(1);
});
im trying to send a value from parent class to child but for some reason im getting props undefined any help?
this is parent class and sending the data to child.
I have added the full child code as requested. im not sure how to add props in as it is a function and when i tried adding props in im still getting props undefined error
{this.state.viewProfile ? (
<SideProfileDrawer
people={this.state.people}
viewprof={this.state.viewProfile}
/>
) : null}
here is me using the props in child
import { makeStyles } from "#material-ui/core/styles";
import InstructionsModal from "./instructionsmodal";
import List from "#material-ui/core/List";
import Divider from "#material-ui/core/Divider";
import React, { Component } from "react";
import Tooltip from "#material-ui/core/Tooltip";
import Drawer from "#material-ui/core/Drawer";
import Zoom from "#material-ui/core/Zoom";
import UserProfile from "../quiz/userProfile";
import { Button } from "react-bootstrap";
import { render } from "react-dom";
import Test from "../quiz/test";
export default function TemporaryDrawer(props) {
const useStyles = makeStyles({
list: {
width: 680
},
fullList: {
width: "auto"
}
});
const classes = useStyles();
const [state, setState] = React.useState({
top: false,
left: false,
bottom: false,
right: false
});
const toggleDrawer = (side, open) => event => {
if (
event.type === "keydown" &&
(event.key === "Tab" || event.key === "Shift")
) {
return;
}
setState({ ...state, [side]: open });
};
const sideList = side => (
<div
className={classes.list}
role="presentation"
onClick={toggleDrawer(side, false)}
onKeyDown={toggleDrawer(side, false)}
>
{this.props.people.map((person, index) => {
return (
<UserProfile
className="userProfile"
levelRook={person.levelRook}
levelStudent={person.levelStudent}
levelIntermediate={person.levelIntermediate}
levelExpert={person.levelExpert}
levelMaster={person.levelMaster}
score={person.Score}
question={person.Questions}
email={person.email}
time={person.lastLogin}
/>
);
})}
</div>
);
return (
<div>
{this.props.viewprof?sideList:null}
<Button onClick={toggleDrawer("right", true)}>Open Right</Button>
<Drawer
anchor="right"
open={state.right}
onClose={toggleDrawer("right", false)}
>
{sideList("right")}
</Drawer>
</div>
);
}
Any help in solving this i tried everything
don't use this.props just use props as you have stateless component not stateful read more
im using react with react-redux and react-router. im working on my blog, in which i have a component with shows list of posts. so everything is working fine but when i get post.id in component it gives me undefined. on the other hand posts are passing to component from container.
please look into my code.
//home_container.js
import { connect } from 'react-redux'
import { show } from './actions'
import HomeComponent from './home_component'
const mapStateToProps = (state) => {
return {
posts: state.posts.data
}
}
const mapDispatchToProps = (dispatch) => {
return {
actions:{
showPosts: (page,limit) => {
show(dispatch,page,limit)
}
}
}
}
const HomeContainer = connect(
mapStateToProps,
mapDispatchToProps
)(HomeComponent)
export default HomeContainer
//home_component.js file
import React, {Component} from 'react';
import Paper from 'material-ui/Paper';
import Style from './styles.css'
import baseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import FlatButton from 'material-ui/FlatButton';
import { Link } from 'react-router'
require('rc-pagination/assets/index.css');
const Pagination = require('rc-pagination');
const style = {
height: "100%",
margin: 10,
padding: 10,
display: 'inline-block',
};
var Detail = React.createClass({
render: function() {
return (
<div >
<div className="row">
<div >
<p>{this.props.post?this.props.post.body.substr(1,600):''}</p>
{this.props.post?
<span style={{"float":"right"}}>
<Link to={`/posts/${this.props.post.id}`}>
<FlatButton
label="Ready more"
labelPosition="before"
primary={true}
/>
</Link>
</span>
:''}
</div>
</div>
</div>
)
}
});
class Index extends Component {
getChildContext() {
return { muiTheme: getMuiTheme(baseTheme) };
}
componentDidMount(){
this.props.actions.showPosts(1,5)
}
render() {
return (
<div >
{this.props.posts.map((post,i) =>
<div className="row" key={i}>
<Paper
style={style}
zDepth={0}
children={<Detail post={post}/>}
/>
)}
</div>
);
}
}
Index.childContextTypes = {
muiTheme: React.PropTypes.object.isRequired,
};
export default Index;
i already check through react-redux inspector. i have posts in posts props of this component, which are sets by container through react redux.
so problem is in the following part of above code.
<Link to={`/posts/${this.props.post.id}`}>
<FlatButton
label="Ready more"
labelPosition="before"
primary={true}
/>
</Link>
Link to tag of react router generate url in this form posts/undefined. because it is considering that post.id is undefined. on the other hand each post have id property and i also checked it through inspection of posts objects.
so problem is in this line this.props.post.id