Diff
checker
텍스트
텍스트
이미지
문서
Excel
폴더
Legal
Enterprise
데스크톱
요금제
로그인
데스크톱 앱 다운로드
텍스트 비교
두 텍스트 파일의 차이점을 찾아보세요
도구
기록
실시간 편집
변경 없는 행 숨기기
줄바꿈 비활성화
레이아웃
나란히 보기
합쳐 보기
비교 단위
스마트
단어
글자
구문 강조
언어 선택
제외
텍스트 변환
첫 변경으로
수정
Diffchecker Desktop
가장 안전하게 Diffchecker를 사용하는 방법. 데스크톱 앱을 사용하면 비교 데이터가 외부로 전송되지 않습니다!
데스크톱 앱 받기
vscode插件i18n-automatically扫描前后jsx的对比图
생성일
2년 전
비교 결과 만료 없음
초기화
내보내기
공유
설명
24 삭제
행
총
삭제
글자
총
삭제
이 기능을 계속 사용하려면 업그레이드해 주세요
Diff
checker
Pro
요금제 보기
194 행
복사
84 추가
행
총
추가
글자
총
추가
이 기능을 계속 사용하려면 업그레이드해 주세요
Diff
checker
Pro
요금제 보기
237 행
복사
복사
복사됨
복사
복사됨
// test.jsx
import i18n from '@/i18n';
// test.jsx
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import PropTypes from 'prop-types';
import PropTypes from 'prop-types';
// 模拟的 API 调用函数
// 模拟的 API 调用函数
const fetchUserData = () => {
const fetchUserData = () => {
return new Promise((resolve) => {
return new Promise((resolve) => {
setTimeout(() => {
setTimeout(() => {
resolve({
resolve({
복사
복사됨
복사
복사됨
name:
'张三'
,
name:
i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-1')
,
age: 30,
age: 30,
복사
복사됨
복사
복사됨
occupation:
'软件工程师'
,
occupation:
i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-2')
,
});
});
}, 1000);
}, 1000);
});
});
};
};
// 错误边界组件
// 错误边界组件
class ErrorBoundary extends React.Component {
class ErrorBoundary extends React.Component {
constructor(props) {
constructor(props) {
super(props);
super(props);
this.state = { hasError: false, error: null };
this.state = { hasError: false, error: null };
}
}
static getDerivedStateFromError(error) {
static getDerivedStateFromError(error) {
return { hasError: true, error };
return { hasError: true, error };
}
}
componentDidCatch(error, errorInfo) {
componentDidCatch(error, errorInfo) {
console.error('错误边界捕获到错误:', error, errorInfo);
console.error('错误边界捕获到错误:', error, errorInfo);
}
}
render() {
render() {
if (this.state.hasError) {
if (this.state.hasError) {
복사
복사됨
복사
복사됨
return
<h2>
很抱歉,出现了错误:
{this.state.error.message}
</h2>
;
return
(
<h2>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-3')}
{this.state.error.message}
</h2>
)
;
}
}
return this.props.children;
return this.props.children;
}
}
}
}
// 头部组件
// 头部组件
const Header = ({ title }) => (
const Header = ({ title }) => (
<header>
<header>
<h1>{title}</h1>
<h1>{title}</h1>
<nav>
<nav>
<ul>
<ul>
<li>
<li>
복사
복사됨
복사
복사됨
<a href="#home">
首页
</a>
<a href="#home">
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-4')}
</a>
</li>
</li>
<li>
<li>
복사
복사됨
복사
복사됨
<a href="#about">
关于我们
</a>
<a href="#about">
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-5')}
</a>
</li>
</li>
<li>
<li>
복사
복사됨
복사
복사됨
<a href="#contact">
联系方式
</a>
<a href="#contact">
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-6')}
</a>
</li>
</li>
</ul>
</ul>
</nav>
</nav>
</header>
</header>
);
);
Header.propTypes = {
Header.propTypes = {
title: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
};
};
// 用户信息组件
// 用户信息组件
const UserInfo = ({ user }) => (
const UserInfo = ({ user }) => (
<div className="user-info">
<div className="user-info">
복사
복사됨
복사
복사됨
<h3>
{user.name}
的个人信息
</h3>
<h3>
<p>
年龄:
{user.age}
</p>
{user.name}
<p>
职业:
{user.occupation}
</p>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-7')}
</h3>
<p>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-8')}
{user.age}
</p>
<p>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-9')}
{user.occupation}
</p>
</div>
</div>
);
);
// 计数器组件
// 计数器组件
const Counter = () => {
const Counter = () => {
const [count, setCount] = useState(0);
const [count, setCount] = useState(0);
const increment = () => setCount((prevCount) => prevCount + 1);
const increment = () => setCount((prevCount) => prevCount + 1);
const decrement = () => setCount((prevCount) => prevCount - 1);
const decrement = () => setCount((prevCount) => prevCount - 1);
return (
return (
<div>
<div>
복사
복사됨
복사
복사됨
<h3>
计数器
</h3>
<h3>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-10')}
</h3>
<p>
当前计数:
{count}
</p>
<p>
<button onClick={increment}>
增加
</button>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-11')}
<button onClick={decrement}>
减少
</button>
{count}
</p>
<button onClick={increment}>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-12')}
</button>
<button onClick={decrement}>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-13')}
</button>
</div>
</div>
);
);
};
};
// 待办事项组件
// 待办事项组件
const TodoList = () => {
const TodoList = () => {
const [todos, setTodos] = useState([]);
const [todos, setTodos] = useState([]);
const [inputValue, setInputValue] = useState('');
const [inputValue, setInputValue] = useState('');
const handleInputChange = (e) => setInputValue(e.target.value);
const handleInputChange = (e) => setInputValue(e.target.value);
const handleSubmit = (e) => {
const handleSubmit = (e) => {
e.preventDefault();
e.preventDefault();
if (inputValue.trim()) {
if (inputValue.trim()) {
setTodos([
setTodos([
...todos,
...todos,
{ id: Date.now(), text: inputValue, completed: false },
{ id: Date.now(), text: inputValue, completed: false },
]);
]);
setInputValue('');
setInputValue('');
}
}
};
};
const toggleTodo = (id) => {
const toggleTodo = (id) => {
setTodos(
setTodos(
todos.map((todo) =>
todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo,
todo.id === id ? { ...todo, completed: !todo.completed } : todo,
),
),
);
);
};
};
return (
return (
<div>
<div>
복사
복사됨
복사
복사됨
<h3>
待办事项
</h3>
<h3>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-14')}
</h3>
<form onSubmit={handleSubmit}>
<form onSubmit={handleSubmit}>
<input
<input
type="text"
type="text"
value={inputValue}
value={inputValue}
onChange={handleInputChange}
onChange={handleInputChange}
복사
복사됨
복사
복사됨
placeholder=
"输入新的待办事项"
placeholder=
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-15')}
/>
/>
복사
복사됨
복사
복사됨
<button type="submit">
添加
</button>
<button type="submit">
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-16')}
</button>
</form>
</form>
<ul>
<ul>
{todos.map((todo) => (
{todos.map((todo) => (
<li
<li
key={todo.id}
key={todo.id}
onClick={() => toggleTodo(todo.id)}
onClick={() => toggleTodo(todo.id)}
style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
>
>
{todo.text}
{todo.text}
</li>
</li>
))}
))}
</ul>
</ul>
</div>
</div>
);
);
};
};
// 主应用组件
// 主应用组件
const App = () => {
const App = () => {
const [user, setUser] = useState(null);
const [user, setUser] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
useEffect(() => {
fetchUserData()
fetchUserData()
.then((data) => {
.then((data) => {
setUser(data);
setUser(data);
setIsLoading(false);
setIsLoading(false);
})
})
.catch((err) => {
.catch((err) => {
복사
복사됨
복사
복사됨
setError(
'获取用户数据时出错')
;
setError(
i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-17'))
;
setIsLoading(false);
setIsLoading(false);
console.error('获取用户数据失败:', err);
console.error('获取用户数据失败:', err);
});
});
}, []);
}, []);
const welcomeMessage = useMemo(() => {
const welcomeMessage = useMemo(() => {
복사
복사됨
복사
복사됨
return user
? `
欢迎回来,
${user.name}!`
:
'欢迎来到我们的应用!'
;
return user
? `
${i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-18')}
${user.name}!`
:
i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-19')
;
}, [user]);
}, [user]);
const handleError = useCallback(() => {
const handleError = useCallback(() => {
throw new Error('这是一个故意抛出的错误');
throw new Error('这是一个故意抛出的错误');
}, []);
}, []);
복사
복사됨
복사
복사됨
if (isLoading)
return <div>
加载中,请稍候...
</div>;
if (isLoading)
if (error)
return
<div>
错误:
{error}
</div>
;
return <div>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-20')}
</div>;
if (error)
return
(
<div>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-21')}
{error}
</div>
)
;
return (
return (
<ErrorBoundary>
<ErrorBoundary>
<div className="app">
<div className="app">
복사
복사됨
복사
복사됨
<Header
title=
"我的 React 应用"
/>
<Header
title=
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-22')}
/>
<main>
<main>
<h2>{welcomeMessage}</h2>
<h2>{welcomeMessage}</h2>
{user && <UserInfo user={user} />}
{user && <UserInfo user={user} />}
<Counter />
<Counter />
<TodoList />
<TodoList />
복사
복사됨
복사
복사됨
<button onClick={handleError}>
点击触发错误
</button>
<button onClick={handleError}>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-23')}
</button>
</main>
</main>
<footer>
<footer>
복사
복사됨
복사
복사됨
<p>
© 2024 我的 React 应用。保留所有权利。
</p>
<p>
{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-24')}
</p>
</footer>
</footer>
</div>
</div>
</ErrorBoundary>
</ErrorBoundary>
);
);
};
};
export default App;
export default App;
저장된 비교 결과
원본
파일 열기
// test.jsx import React, { useState, useEffect, useCallback, useMemo } from 'react'; import PropTypes from 'prop-types'; // 模拟的 API 调用函数 const fetchUserData = () => { return new Promise((resolve) => { setTimeout(() => { resolve({ name: '张三', age: 30, occupation: '软件工程师', }); }, 1000); }); }; // 错误边界组件 class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false, error: null }; } static getDerivedStateFromError(error) { return { hasError: true, error }; } componentDidCatch(error, errorInfo) { console.error('错误边界捕获到错误:', error, errorInfo); } render() { if (this.state.hasError) { return <h2>很抱歉,出现了错误:{this.state.error.message}</h2>; } return this.props.children; } } // 头部组件 const Header = ({ title }) => ( <header> <h1>{title}</h1> <nav> <ul> <li> <a href="#home">首页</a> </li> <li> <a href="#about">关于我们</a> </li> <li> <a href="#contact">联系方式</a> </li> </ul> </nav> </header> ); Header.propTypes = { title: PropTypes.string.isRequired, }; // 用户信息组件 const UserInfo = ({ user }) => ( <div className="user-info"> <h3>{user.name}的个人信息</h3> <p>年龄:{user.age}</p> <p>职业:{user.occupation}</p> </div> ); // 计数器组件 const Counter = () => { const [count, setCount] = useState(0); const increment = () => setCount((prevCount) => prevCount + 1); const decrement = () => setCount((prevCount) => prevCount - 1); return ( <div> <h3>计数器</h3> <p>当前计数:{count}</p> <button onClick={increment}>增加</button> <button onClick={decrement}>减少</button> </div> ); }; // 待办事项组件 const TodoList = () => { const [todos, setTodos] = useState([]); const [inputValue, setInputValue] = useState(''); const handleInputChange = (e) => setInputValue(e.target.value); const handleSubmit = (e) => { e.preventDefault(); if (inputValue.trim()) { setTodos([ ...todos, { id: Date.now(), text: inputValue, completed: false }, ]); setInputValue(''); } }; const toggleTodo = (id) => { setTodos( todos.map((todo) => todo.id === id ? { ...todo, completed: !todo.completed } : todo, ), ); }; return ( <div> <h3>待办事项</h3> <form onSubmit={handleSubmit}> <input type="text" value={inputValue} onChange={handleInputChange} placeholder="输入新的待办事项" /> <button type="submit">添加</button> </form> <ul> {todos.map((todo) => ( <li key={todo.id} onClick={() => toggleTodo(todo.id)} style={{ textDecoration: todo.completed ? 'line-through' : 'none' }} > {todo.text} </li> ))} </ul> </div> ); }; // 主应用组件 const App = () => { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetchUserData() .then((data) => { setUser(data); setIsLoading(false); }) .catch((err) => { setError('获取用户数据时出错'); setIsLoading(false); console.error('获取用户数据失败:', err); }); }, []); const welcomeMessage = useMemo(() => { return user ? `欢迎回来,${user.name}!` : '欢迎来到我们的应用!'; }, [user]); const handleError = useCallback(() => { throw new Error('这是一个故意抛出的错误'); }, []); if (isLoading) return <div>加载中,请稍候...</div>; if (error) return <div>错误:{error}</div>; return ( <ErrorBoundary> <div className="app"> <Header title="我的 React 应用" /> <main> <h2>{welcomeMessage}</h2> {user && <UserInfo user={user} />} <Counter /> <TodoList /> <button onClick={handleError}>点击触发错误</button> </main> <footer> <p>© 2024 我的 React 应用。保留所有权利。</p> </footer> </div> </ErrorBoundary> ); }; export default App;
수정본
파일 열기
import i18n from '@/i18n'; // test.jsx import React, { useState, useEffect, useCallback, useMemo } from 'react'; import PropTypes from 'prop-types'; // 模拟的 API 调用函数 const fetchUserData = () => { return new Promise((resolve) => { setTimeout(() => { resolve({ name: i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-1'), age: 30, occupation: i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-2'), }); }, 1000); }); }; // 错误边界组件 class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false, error: null }; } static getDerivedStateFromError(error) { return { hasError: true, error }; } componentDidCatch(error, errorInfo) { console.error('错误边界捕获到错误:', error, errorInfo); } render() { if (this.state.hasError) { return ( <h2> {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-3')} {this.state.error.message} </h2> ); } return this.props.children; } } // 头部组件 const Header = ({ title }) => ( <header> <h1>{title}</h1> <nav> <ul> <li> <a href="#home"> {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-4')} </a> </li> <li> <a href="#about"> {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-5')} </a> </li> <li> <a href="#contact"> {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-6')} </a> </li> </ul> </nav> </header> ); Header.propTypes = { title: PropTypes.string.isRequired, }; // 用户信息组件 const UserInfo = ({ user }) => ( <div className="user-info"> <h3> {user.name} {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-7')} </h3> <p> {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-8')} {user.age} </p> <p> {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-9')} {user.occupation} </p> </div> ); // 计数器组件 const Counter = () => { const [count, setCount] = useState(0); const increment = () => setCount((prevCount) => prevCount + 1); const decrement = () => setCount((prevCount) => prevCount - 1); return ( <div> <h3>{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-10')}</h3> <p> {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-11')} {count} </p> <button onClick={increment}> {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-12')} </button> <button onClick={decrement}> {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-13')} </button> </div> ); }; // 待办事项组件 const TodoList = () => { const [todos, setTodos] = useState([]); const [inputValue, setInputValue] = useState(''); const handleInputChange = (e) => setInputValue(e.target.value); const handleSubmit = (e) => { e.preventDefault(); if (inputValue.trim()) { setTodos([ ...todos, { id: Date.now(), text: inputValue, completed: false }, ]); setInputValue(''); } }; const toggleTodo = (id) => { setTodos( todos.map((todo) => todo.id === id ? { ...todo, completed: !todo.completed } : todo, ), ); }; return ( <div> <h3>{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-14')}</h3> <form onSubmit={handleSubmit}> <input type="text" value={inputValue} onChange={handleInputChange} placeholder={i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-15')} /> <button type="submit"> {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-16')} </button> </form> <ul> {todos.map((todo) => ( <li key={todo.id} onClick={() => toggleTodo(todo.id)} style={{ textDecoration: todo.completed ? 'line-through' : 'none' }} > {todo.text} </li> ))} </ul> </div> ); }; // 主应用组件 const App = () => { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetchUserData() .then((data) => { setUser(data); setIsLoading(false); }) .catch((err) => { setError(i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-17')); setIsLoading(false); console.error('获取用户数据失败:', err); }); }, []); const welcomeMessage = useMemo(() => { return user ? `${i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-18')}${user.name}!` : i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-19'); }, [user]); const handleError = useCallback(() => { throw new Error('这是一个故意抛出的错误'); }, []); if (isLoading) return <div>{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-20')}</div>; if (error) return ( <div> {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-21')} {error} </div> ); return ( <ErrorBoundary> <div className="app"> <Header title={i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-22')} /> <main> <h2>{welcomeMessage}</h2> {user && <UserInfo user={user} />} <Counter /> <TodoList /> <button onClick={handleError}> {i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-23')} </button> </main> <footer> <p>{i18n.t('demoTest-test-jsx-befor-192991598bc5aa541-24')}</p> </footer> </div> </ErrorBoundary> ); }; export default App;
비교하기